首页 新闻 会员 周边

关于Ninject在MVC中的引用问题

0
悬赏园豆:30 [已解决问题] 解决于 2012-06-12 17:46

现在用mvc3+Ninject(IOC)+三层架构开发一个网站,现在为了能够依赖注入,必须要在WEB层引用DAL,不然NinjectWebCommon.cs里没法配置注入,请问如何不引用DAL也能使用ninject来注入?

架构如下:

问题补充:

http://files.cnblogs.com/diablo3/demosite.rar 

 

这个是方案源文件

flytothemoon的主页 flytothemoon | 初学一级 | 园豆:111
提问于:2012-06-12 15:09
< >
分享
最佳答案
2

把Ninject放在独立的项目中

收获园豆:20
dudu | 高人七级 |园豆:31003 | 2012-06-12 16:01

我试一试

flytothemoon | 园豆:111 (初学一级) | 2012-06-12 16:13

老大来点实例代码啊

无尽思绪 | 园豆:94 (初学一级) | 2012-06-12 16:14

@flytothemoon: 需要在AssemblyInfo.cs中加上类似这样的代码:

[assembly: PreApplicationStartMethod(typeof(BootStrapper.Initializer), "Initialize")]
dudu | 园豆:31003 (高人七级) | 2012-06-12 16:15

@dudu:  请问

BootStrapper是在哪个assembly里面? 
需要引用那些extenstion?
无尽思绪 | 园豆:94 (初学一级) | 2012-06-19 15:13

@无尽思绪: 这是自己定义的,比如:

namespace BootStrapper
{
    public static class Initializer
    {
        public static void Initialize()
        {
        }
    }
}
dudu | 园豆:31003 (高人七级) | 2012-06-19 15:27
其他回答(2)
2

DAL是比如要引入的吧。

不管怎么说,WEBUI下都需要DAL.dll文件的啊。

收获园豆:10
无尽思绪 | 园豆:94 (初学一级) | 2012-06-12 15:17

我个人在考虑使用配置文件来实现

private void AddBindings()
        {
            // 这里实现重配置文件读取,而不是显示的绑定


            ninjectKernel.Bind<IProductRepository>().To<EFProductRepository>();
        }

我的

IProductRepository和
EFProductRepository都在DAL里面。
支持(0) 反对(0) 无尽思绪 | 园豆:94 (初学一级) | 2012-06-12 15:22

是吗,这样看着有点不爽,呵呵。 DAL里是数据访问类和接口,BLL里用Facade模式的业务接口,WEB里调用BLL业务接口,注入了2个地方

支持(0) 反对(0) flytothemoon | 园豆:111 (初学一级) | 2012-06-12 15:31

@flytothemoon: 

Global.asax的Application_Start添加

ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory());
NinjectControllerFactory里面的AddBindding实现从xml/config读取依赖关系。

有何不妥?
还有一点,你想注入的是什么?
我感觉你应该注入的是BLL, 而不是DAL, 但是BLL比如引用DAL.
支持(0) 反对(0) 无尽思绪 | 园豆:94 (初学一级) | 2012-06-12 15:34

@flytothemoon: 

你看看我注入的是什么东西:

ninjectKernel.Bind<IProductRepository>().To<EFProductRepository>();
这个其实不是最直接的DAL. 你可以看成BLL。

在EFProductRepository里面实现对DAL的封装。
支持(0) 反对(0) 无尽思绪 | 园豆:94 (初学一级) | 2012-06-12 15:37

@flytothemoon: 再详细一点,看看我的图片。

支持(0) 反对(0) 无尽思绪 | 园豆:94 (初学一级) | 2012-06-12 15:42

@无尽思绪: 我看看先

支持(0) 反对(0) flytothemoon | 园豆:111 (初学一级) | 2012-06-12 15:43

@flytothemoon: 哦,还有一点,我在Controller里面,使用的是构造函数注入,如:

public ProductController(IProductRepository productRepository)
        {
            repository = productRepository;
        }
支持(0) 反对(0) 无尽思绪 | 园豆:94 (初学一级) | 2012-06-12 15:48

@无尽思绪: 我也是构造函数注入,BLL里业务类引用DAL的数据访问接口注入了一次,WEB里引用BLL时注入了BLL的业务接口

支持(0) 反对(0) flytothemoon | 园豆:111 (初学一级) | 2012-06-12 15:53

@flytothemoon: 

“BLL里业务类引用DAL的数据访问接口注入了一次” - 这个地方不需要在ninject里面显示绑定的

ninject会自动注入。 

 

只需要绑定注入:WEB里引用BLL时注入了BLL的业务接口

支持(0) 反对(0) 无尽思绪 | 园豆:94 (初学一级) | 2012-06-12 16:00

@无尽思绪: 会报错 No matching bindings are available, and the type is not self-bindable.  Ninject刚上手的,还不太熟

支持(0) 反对(0) flytothemoon | 园豆:111 (初学一级) | 2012-06-12 16:13
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DAL;
using MODEL;

namespace BLL
{
    public class service:Iservice
    {

        #region Iservice Members

        private Iuser user;
        private Iitem item;

        public service(Iuser _user, Iitem _item)
        {
            user = _user;
            item = _item;
        }

        public void uname(model m)
        {
            user.uname(m);
        }

        public void itemid(model m)
        {
            item.itemid(m);
        }

        #endregion
    }
}

这个是BLL的类

 

 

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using BLL;
using MODEL;

namespace webUI.Controllers
{
    public class HomeController : Controller
    {
        //
        // GET: /Home/
        Iservice service;

        public HomeController(Iservice _service)
        {
            service = _service;
        }

        public ActionResult Index()
        {
            model m = new model();
            m.name = "111";
            m.id = 1;
            service.uname(m);
            service.itemid(m);
            ViewBag.name = m.name;
            ViewBag.id = m.id;
            return View();
        }

    }
}

这个是WEB里注入的

支持(0) 反对(0) flytothemoon | 园豆:111 (初学一级) | 2012-06-12 16:48

@flytothemoon: 看了你的源代码,我的方式和你的不一样,看下面代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Ninject;
using System.Web.Routing;
using SportsStore.Domain.Abstract;
using Moq;
using SportsStore.Domain.Entities;
using SportsStore.Domain.Concrete;

namespace SportsStore.WebUI.Infrastructure
{
    public class NinjectControllerFactory : DefaultControllerFactory
    {
        private IKernel ninjectKernel;
        public NinjectControllerFactory()
        {
            ninjectKernel = new StandardKernel();
            AddBindings();
        }
        protected override IController GetControllerInstance(RequestContext requestContext,
        Type controllerType)
        {
            return controllerType == null
            ? null
            : (IController)ninjectKernel.Get(controllerType);
        }
        private void AddBindings()
        {
            // Mock implementation of the IProductRepository Interface
            //Mock<IProductRepository> mock = new Mock<IProductRepository>();
            //mock.Setup(m => m.Products).Returns(new List<Product> {
            //    new Product { Name = "Football", Price = 25 },
            //    new Product { Name = "Surf board", Price = 179 },
            //    new Product { Name = "Running shoes", Price = 95 }
            //    }.AsQueryable());


            ninjectKernel.Bind<IProductRepository>().To<EFProductRepository>();
        }
    }
}

上面的代码在独立的一个文件中:NinjectControllerFactory.cs

修改Global.asmx:

protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();

            RegisterGlobalFilters(GlobalFilters.Filters);
            RegisterRoutes(RouteTable.Routes);

//这行
            ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory());

            BundleTable.Bundles.RegisterTemplateBundles();

        }
支持(0) 反对(0) 无尽思绪 | 园豆:94 (初学一级) | 2012-06-12 16:55

@无尽思绪: return controllerType == null?null:(IController)ninjectKernel.Get(controllerType);  这里报错了

支持(0) 反对(0) flytothemoon | 园豆:111 (初学一级) | 2012-06-12 17:11

@flytothemoon: 

1. 可能是相关引用没添加

2. 新的NinjectControllerFactory并没有返回默认的Controller=Home, 所以你需要在RegisterRoutes(Global.asax)里面配置当前的路由。

 

另外,你具体的错误是啥?

支持(0) 反对(0) 无尽思绪 | 园豆:94 (初学一级) | 2012-06-12 17:13

@无尽思绪: Error activating Iuser
No matching bindings are available, and the type is not self-bindable.
Activation path:
 3) Injection of dependency Iuser into parameter _user of constructor of type service
 2) Injection of dependency Iservice into parameter _service of constructor of type HomeController
 1) Request for HomeController

支持(0) 反对(0) flytothemoon | 园豆:111 (初学一级) | 2012-06-12 17:18

@flytothemoon: 

你现在的绑定代码是如何的?

支持(0) 反对(0) 无尽思绪 | 园豆:94 (初学一级) | 2012-06-12 17:19

@无尽思绪: 
            ninjectKernel.Bind<BLL.Iservice>().To<BLL.service>();
我试了了下,加入DAL引用,增加这2个就不报错了,但这和之前就没区别咯
            ninjectKernel.Bind<DAL.Iitem>().To<DAL.item>();
            ninjectKernel.Bind<DAL.Iuser>().To<DAL.user>();

支持(0) 反对(0) flytothemoon | 园豆:111 (初学一级) | 2012-06-12 17:23

@flytothemoon: 我用你的代码试了一下,确实如你所说。是我以前理解错误了。确实要另外绑定Item和User才没有错误。 抱歉。

自动绑定代码:

看看这里:http://frankmao.com/2011/03/22/ninject-auto-binding/

支持(0) 反对(0) 无尽思绪 | 园豆:94 (初学一级) | 2012-06-12 17:40

@无尽思绪: 呵呵 我看看,谢谢了,我再试试独立出来

支持(0) 反对(0) flytothemoon | 园豆:111 (初学一级) | 2012-06-12 17:42
0

楼主的问你解决了么?我也遇到这样的疑惑了,是不是Ninject不适合在多层中实现IOC哦。我看很多都是说MVC中用Ninject实现注入,而且实例也很简单。但无论怎样他们在UI层 去绑定接口与实现的关系,这样导致UI层要添加BLL和DAL层的引用。

我的想法是新建一层....命名空间.Ninject  然后在里面写 NinjectModule:Ninject.Modules.NinjectModule(这个名字可能错了,反正就是去实现Ninject那个模块 然后重新额Loading方法) 然后在Loding方法中去绑定关系。这样UI只会引用IBLL和IDAL+....命名空间.Ninject 

 

还有个问题就是Ninject这种注入方式虽然提供了配置文件的绑定方式,但是好像它本身不推荐,但是不用配置文件的方式那遇到要修改是是否需要关闭程序,修改后重新编译?

 

最后一个问题 Bind<接口>().to<实现类>() 这个语句是不是根据项目里面里的数量要写很多很多很多..很多...多.....多

变形精怪 | 园豆:5 (初学一级) | 2013-08-01 09:51
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册