最近休假了所以沒有及時更新這一系列文章,大家見諒。本來想先寫NuGet這部分的,但是我覺得NuGet對於大家來說可以先不用話費太多時間,還是先瞭解下ASP.NET MVC 3中的DI這部分吧。
ASP.NET MVC 3.0學習系列文章—序
ASP.NET MVC 3.0學習系列文章--Razor and ASP.NET MVC 3.0
ASP.NET MVC 3.0學習系列文章—Controllers in ASP.NET MVC 3.0
ASP.NET MVC 3.0學習系列文章—Model in ASP.NET MVC 3.0
這篇文章主要介紹如下內容:
1.Introduction
對於DI,工作3年以上的開發人員應該都是比較熟悉了。如果你是比較初級的開發人員,我建議可以看看資料,瞭解下DI以及相關的概念。推薦閱讀如下:
http://en.wikipedia.org/wiki/Dependency_injection
http://en.wikipedia.org/wiki/Abstract_factory
http://martinfowler.com/articles/injection.html#UsingAServiceLocator
在ASP.NET MVC 3之前的版本是使用Abstract Factory,Service Locator來作為DI的容器,而在3中你可以使用新的Dependency Resolver來結合Container工具更加簡單的實現DI。
2. Dependency Resolution
什麼是Dependency Resolution?
一個Controller需要一個Repository,那麼這個Repository就是Controller的一個依賴項。
上面是傳統的一個Deoendency的使用例子(代碼中)。
在ASP.NET MVC 3中提供了Dependency Reolver,它給我們提供了一個好的Dependency Resolution。
當請求中需要某個組件時,Dependency Resolver就會對應的提供一個控制項T。
3.Benefits
使用Dependency Resolution有啥好處呢?
a.Flexibility
讓整個系統的架構更加靈活。開發人員可以更加專註於架構,而不是功能的實現。
b.Testability
讓整個系統的測試更加容易。測試部分和具體的功能實現依賴項要小很多了。
c.Extensibility
可擴充性增強。
4.IdependencyResolver的使用
The DependencyResolver is a member of the System.Web.Mvc NameSpace and its job is quite simple: to provide a central registration point for your chosen IoC Container. Prior to MVC 3, we often dealt with our chosen IoC container directly. In MVC 3, there is an abstraction layer (the DependencyResolver Class) that we will interact with directly. Whether your chosen IoC Container is Windsor, StructureMap or Unity, you can take advantage of this new feature.
IdependencyResolver介面有兩個方法:
object GetService(Type serviceType) IEnumerable<object> GetServices(Type serviceType)
如何使用它呢,一般都是讓結合一個IoC Container來使用。
我這裡給出幾個例子:
結合Autofac使用:
我比較喜歡Autofac,但是發現結合IdependencyResolver來使用Autoc相對還是比較複雜的。需要好好研究研究。
結合StructureMap:
1. public class StructureMapDependencyResolver : IDependencyResolver 2. { 3. IContainer _container; 4. 5. public StructureMapDependencyResolver(IContainer container) 6. { 7. _container = container; 8. } 9. 10. 11. public object GetService(Type serviceType) 12. { 13. object instance = _container.TryGetInstance(serviceType); 14. 15. if (instance == null && !serviceType.IsAbstract) 16. { 17. _container.Configure(c => c.AddType(serviceType, serviceType)); 18. instance = _container.TryGetInstance(serviceType); 19. } 20. 21. return instance; 22. } 23. 24. public IEnumerable<object> GetServices(Type serviceType) 25. { 26. return _container.GetAllInstances(serviceType).Cast<object>(); 27. } 28. }
結合Unity:
1. public class UnityDependencyResolver : IDependencyResolver 2. { 3. IUnityContainer _container; 4. 5. public UnityDependencyResolver(IUnityContainer container) 6. { 7. _container = container; 8. } 9. 10. public object GetService(Type serviceType) 11. { 12. object instance; 13. try 14. { 15. instance = _container.Resolve(serviceType); 16. if (serviceType.IsAbstract || serviceType.IsInterface) 17. { 18. return null; 19. } 20. return instance; 21. } 22. catch (Exception e) 23. { 24. return null; 25. } 26. } 27. 28. public IEnumerable<object> GetServices(Type serviceType) 29. { 30. return _container.ResolveAll(serviceType); 31. } 32. }
結合NInject:
public class NinjectDependencyResolver : IDependencyResolver { private readonly IKernel _kernel; public NinjectDependencyResolver(IKernel kernel) { _kernel = kernel; } public object GetService(Type serviceType) { return _kernel.TryGet(serviceType, new IParameter[0]); } public IEnumerable<object> GetServices(Type serviceType) { return _kernel.GetAll(serviceType, new IParameter[0]); } }
接下來是就是在Application Start時Register Service並設定Resolver。
StructureMap:
# IContainer container = new Container(# x =># {# x.For<SomeService>().# Use<SomeService>().# WithCtorArg("stringResponse").# EqualTo("IoC Container: StructureMap.");# # x.For<HomeController>().Use<HomeController>();# });# DependencyResolver.SetResolver(new StructureMapDependencyResolver(container));
Unity:
## var container = new UnityContainer();# # container# .RegisterType<SomeService, SomeService>().# Configure<InjectedMembers>().ConfigureInjectionFor# <SomeService>(new InjectionConstructor("IoC Container: Unity."));# # container.RegisterType<HomeController, HomeController>();# # DependencyResolver.SetResolver(new UnityDependencyResolver(container));
NInject:
var kernel = new StandardKernel(); kernel.Bind<IMessenger>().To<SmsMessenger>(); kernel.Bind<IFilterProvider>().To<MessagingFilterProvider>(); DependencyResolver.SetResolver(new NinjectDependencyResolver(kernel));
5.Controller Injection:
6.View Injection:
你可以閱讀這篇文章:http://www.lostechies.com/blogs/johnvpetersen/archive/2011/01/24/dependency-injection-in-mvc-3-with-views.aspx
關於Activator和ViewEngine我們另外寫一文章介紹。
Nick