把Ninject放在独立的项目中
我试一试
老大来点实例代码啊
@flytothemoon: 需要在AssemblyInfo.cs中加上类似这样的代码:
[assembly: PreApplicationStartMethod(typeof(BootStrapper.Initializer), "Initialize")]
@dudu: 请问
BootStrapper是在哪个assembly里面?
需要引用那些extenstion?
@无尽思绪: 这是自己定义的,比如:
namespace BootStrapper { public static class Initializer { public static void Initialize() { } } }
DAL是比如要引入的吧。
不管怎么说,WEBUI下都需要DAL.dll文件的啊。
我个人在考虑使用配置文件来实现
private void AddBindings() { // 这里实现重配置文件读取,而不是显示的绑定 ninjectKernel.Bind<IProductRepository>().To<EFProductRepository>(); }
我的
IProductRepository和
EFProductRepository都在DAL里面。
是吗,这样看着有点不爽,呵呵。 DAL里是数据访问类和接口,BLL里用Facade模式的业务接口,WEB里调用BLL业务接口,注入了2个地方
@flytothemoon:
Global.asax的Application_Start添加
ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory());
NinjectControllerFactory里面的AddBindding实现从xml/config读取依赖关系。
有何不妥?
还有一点,你想注入的是什么?
我感觉你应该注入的是BLL, 而不是DAL, 但是BLL比如引用DAL.
@flytothemoon:
你看看我注入的是什么东西:
ninjectKernel.Bind<IProductRepository>().To<EFProductRepository>();
这个其实不是最直接的DAL. 你可以看成BLL。
在EFProductRepository里面实现对DAL的封装。
@flytothemoon: 再详细一点,看看我的图片。
@无尽思绪: 我看看先
@flytothemoon: 哦,还有一点,我在Controller里面,使用的是构造函数注入,如:
public ProductController(IProductRepository productRepository) { repository = productRepository; }
@无尽思绪: 我也是构造函数注入,BLL里业务类引用DAL的数据访问接口注入了一次,WEB里引用BLL时注入了BLL的业务接口
@flytothemoon:
“BLL里业务类引用DAL的数据访问接口注入了一次” - 这个地方不需要在ninject里面显示绑定的
ninject会自动注入。
只需要绑定注入:WEB里引用BLL时注入了BLL的业务接口
@无尽思绪: 会报错 No matching bindings are available, and the type is not self-bindable. Ninject刚上手的,还不太熟
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里注入的
@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(); }
@无尽思绪: return controllerType == null?null:(IController)ninjectKernel.Get(controllerType); 这里报错了
@flytothemoon:
1. 可能是相关引用没添加
2. 新的NinjectControllerFactory并没有返回默认的Controller=Home, 所以你需要在RegisterRoutes(Global.asax)里面配置当前的路由。
另外,你具体的错误是啥?
@无尽思绪: 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
@flytothemoon:
你现在的绑定代码是如何的?
@无尽思绪:
ninjectKernel.Bind<BLL.Iservice>().To<BLL.service>();
我试了了下,加入DAL引用,增加这2个就不报错了,但这和之前就没区别咯
ninjectKernel.Bind<DAL.Iitem>().To<DAL.item>();
ninjectKernel.Bind<DAL.Iuser>().To<DAL.user>();
@flytothemoon: 我用你的代码试了一下,确实如你所说。是我以前理解错误了。确实要另外绑定Item和User才没有错误。 抱歉。
自动绑定代码:
@无尽思绪: 呵呵 我看看,谢谢了,我再试试独立出来
楼主的问你解决了么?我也遇到这样的疑惑了,是不是Ninject不适合在多层中实现IOC哦。我看很多都是说MVC中用Ninject实现注入,而且实例也很简单。但无论怎样他们在UI层 去绑定接口与实现的关系,这样导致UI层要添加BLL和DAL层的引用。
我的想法是新建一层....命名空间.Ninject 然后在里面写 NinjectModule:Ninject.Modules.NinjectModule(这个名字可能错了,反正就是去实现Ninject那个模块 然后重新额Loading方法) 然后在Loding方法中去绑定关系。这样UI只会引用IBLL和IDAL+....命名空间.Ninject
还有个问题就是Ninject这种注入方式虽然提供了配置文件的绑定方式,但是好像它本身不推荐,但是不用配置文件的方式那遇到要修改是是否需要关闭程序,修改后重新编译?
最后一个问题 Bind<接口>().to<实现类>() 这个语句是不是根据项目里面里的数量要写很多很多很多..很多...多.....多