我们通过Ninject(http://www.ninject.org/)项目来帮助我们实现MVC.Net与WebAPI项目的IOC实现。
首先我们来看MVC.Net的IOC实现。
1. 通过NuGet我们安装Ninject.MVC3,它会同时安装Ninject、Ninject.Web.Common和Ninject.Web.Common.WebHost。不用被它的名字干扰,它对MVC.Net 5也是适用的。
2. 安装成功后,在MVC.Net的App_Start目录中会多出一个NinjectWebCommon.cs文件。
3. 打开此文件,然后在RegisterServices方法中添加类的绑定,例如:
1 private static void RegisterServices(IKernel kernel) 2 { 3 // DBContext必须要per Http Request per Instance。 4 kernel.Bind<DemoModelContainer>().ToSelf().InRequestScope(); 5 6 kernel.Bind<IPostService>().To<PostService>(); 7 8 kernel.Bind<IPostRepository>().To<PostRepository>(); 9 }
4. 这时我们就可以在直接在类中引用接口,而不用是指定该接口是由哪个具体类实现的。例如:
1 private DemoModelContainer _dbContext; 2 3 private IPostService _postService; 4 5 public PostController(DemoModelContainer dbContext, IPostService postService) 6 { 7 _dbContext = dbContext; 8 9 _postService = postService; 10 }
5. 在系统运行后,Ninject会自动将接口对应的类给传入构造函数中。另外还有个有趣的代码就是DemoModelContainer。这个类不是一个接口,是一个EntityFramework的DBContext。在这里我们之所以使用Ninject来管理,是为了实现自动针对每个Request来实例化DBContext,同时又能保证在Request销毁后,对应的DBContext实例也同时销毁。如果不通过Ninject,那么我们就需要给每个Controller实现Dispose方法,然后显式销毁。
========================================
对于WebAPI来说,除了以上步骤,还需要多操作几步:
1. 创建NinjectResolver.cs和NinjectScope.cs两个类文件,代码如下:
NinjectResolver.cs
1 using Ninject; 2 using System; 3 using System.Collections.Generic; 4 using System.Linq; 5 using System.Web; 6 using System.Web.Http.Dependencies; 7 8 namespace NinjectWebApi.Models 9 { 10 public class NinjectResolver : NinjectScope, IDependencyResolver 11 { 12 private IKernel _kernel; 13 public NinjectResolver(IKernel kernel) 14 : base(kernel) 15 { 16 _kernel = kernel; 17 } 18 public IDependencyScope BeginScope() 19 { 20 return new NinjectScope(_kernel.BeginBlock()); 21 } 22 } 23 }
NinjectScope.cs
1 using Ninject.Activation; 2 using Ninject.Parameters; 3 using Ninject.Syntax; 4 using System; 5 using System.Collections.Generic; 6 using System.Linq; 7 using System.Web.Http.Dependencies; 8 9 namespace NinjectWebApi.Models 10 { 11 public class NinjectScope : IDependencyScope 12 { 13 protected IResolutionRoot resolutionRoot; 14 15 public NinjectScope(IResolutionRoot kernel) 16 { 17 resolutionRoot = kernel; 18 } 19 20 public object GetService(Type serviceType) 21 { 22 IRequest request = resolutionRoot.CreateRequest(serviceType, null, new Parameter[0], true, true); 23 return resolutionRoot.Resolve(request).SingleOrDefault(); 24 } 25 26 public IEnumerable<object> GetServices(Type serviceType) 27 { 28 IRequest request = resolutionRoot.CreateRequest(serviceType, null, new Parameter[0], true, true); 29 return resolutionRoot.Resolve(request).ToList(); 30 } 31 32 public void Dispose() 33 { 34 IDisposable disposable = (IDisposable)resolutionRoot; 35 if (disposable != null) disposable.Dispose(); 36 resolutionRoot = null; 37 } 38 } 39 }
2. 修改NinjectWebCommon.cs的CreateKernel方法:
1 private static IKernel CreateKernel() 2 { 3 var kernel = new StandardKernel(); 4 try 5 { 6 kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel); 7 kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>(); 8 9 RegisterServices(kernel); 10 11 // WebApi项目必须添加此行 12 System.Web.Http.GlobalConfiguration.Configuration.DependencyResolver = 13 new NinjectWebApi.Models.NinjectResolver(kernel); 14 15 return kernel; 16 } 17 catch 18 { 19 kernel.Dispose(); 20 throw; 21 } 22 }
其它的操作都和MVC.Net一样,这样WebAPI的IOC也实现了。