ASP.NET MVC中Autofac實現的自動注入模式

熟悉IoC容器的都知道,在開發過程中,最鬱悶的莫過於當你新增一個Service時,你需要對該Service進行註冊,有的是使用代碼注入,有的是XML配置注入,不管是哪種類型的注入,經常會出現開發人員忘記注入的情況,

如果你的頁面是直接發送請求的,那麼會得到類似於如下頁面的錯誤:

image  <- _<-

 

如果該服務是用於AJAX請求實用的,那麼你就悲劇了,因爲頁面只是沒反應,只有查看錯誤日誌了。

 

於是我試着去想辦法去避免每次的服務都需要注入,而是系統自動注入。

image

 

紅色線條框住的地方就是自動注入的代碼實現。很高興Autofac提供一個RegisterAssemblyTypes方法。它回去掃描所有的dll並把每個類註冊爲它所實現的接口。。。。

既然能夠自動注入,那麼接口和類的定義一定要有一定的規律。 從上面的代碼可以看到baseType這個變量,它是IDependency接口的類型。

IDependency接口如下:

image

 

其他任何的接口都需要繼承這個接口,例如我們定義一個接口IModelCar:

image

 

IModelCar的實現類:

 

image

 

自動注入原理說明:

 

 

 

首先我們去找到所有Dll,再去找到實現了IDependency接口的類,然後使用RegisterAssemblyTypes進行注入。

 

在Controller中調用試試:

image

 

可以看到_carmodel解析後爲ModelCar的實例。。 微笑

 

Demo下載: https://github.com/nicholaspei/MvcApplication5

 

標籤: Asp.net MVCAutofac

轉載至http://www.cnblogs.com/n-pei/archive/2013/01/24/2875674.html

轉載至http://www.it165.net/pro/html/201405/14502.html
原理

Autofac是.net界一款輕量化的IOC組件,使用Autofac可以幫助完成代碼中很多依賴注入工作。在以前文章中,介紹過Autofac的配置過程(http://www.cnblogs.com/Jnw-qianxi/p/3450344.html),在我以往的配置過程中,接口與接口的實現類的註冊在一個靜態方法RegisterAutofac中實現:

01.1 public static void RegisterAutofac()
02.2         {
03.3             ContainerBuilder builder = new ContainerBuilder();
04.4             builder.RegisterControllers(Assembly.GetExecutingAssembly());
05.5
06.6             #region IOC註冊區域
07.7        
08.8           
09.9             //Admin
10.10             builder.RegisterType<AdminService>().As<IAdminService>().InstancePerHttpRequest();
11.11
12.12        
13.13             #endregion
14.14             // then
15.15             var container = builder.Build();
16.16             DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
17.17          
18.18         }

    隨着系統開發的進行,IOC註冊區域中會不斷添加新的註冊,不同區域,不同模塊的類型註冊都會在這進行(數據倉儲層,業務邏輯層,基礎設施層等等不同層次的類型註冊都要在此方法中進行),同時系統不同開發人員都需要維護該方法,這樣帶來

1.RegisterAutofac方法所在類的臃腫,且不符合類的職責單一原則。<br><br>  爲此我想到,能否根據註冊類型,將IOC註冊區域部分提取到不同的類中實現,將如這些類擁有一個共同的接口,不是就可以根據接口反射出獲取這些類了嗎?<br>  <br>首先,定義反射類。用於獲取繼承接口的類型
01.1  public class ContainerTypeFinder : ITypeFinder
02.2     {
03.3
04.4         public IList<Assembly> GetAssemblies()
05.5         {
06.6             //由於註冊文件可能分佈在不同類庫,爲此我們獲取所有程序集,而不是當前程序集
07.7             return AppDomain.CurrentDomain.GetAssemblies();
08.8
09.9         }
10.10
11.11         public IEnumerable<Type> FindClassesOfType(Type assignTypeFrom)
12.12         {
13.13             var list = new List<Type>();
14.14             foreach (var item in GetAssemblies())
15.15             {
16.16                 var typesToRegister = item.GetTypes()
17.17               .Where(type => !String.IsNullOrEmpty(type.Namespace))
18.18               .Where(type => type.GetInterface(assignTypeFrom.Name) == assignTypeFrom)
19.19              ;
20.20                 if (typesToRegister.Count() > 0)
21.21                 {
22.22                     list.AddRange(typesToRegister);
23.23                 }
24.24             }
25.25             return list;
26.26         }
27.27     }

  然後,就是將IOC註冊區域移除到類當中

01.1  public interface IDependencyRegistrar
02.2     {
03.3         void Register(ContainerBuilder builder);
04.4
05.5         int Order { get; }
06.6     }
07.7
08.8
09.9  public class DependencyRegistrar : IDependencyRegistrar
10.10     {
11.11         public void Register(ContainerBuilder builder)
12.12         {
13.13             builder.RegisterType<EfRepository<Core.Domain.Customer.Customer>>().As<IRepository<Core.Domain.Customer.Customer>>().InstancePerHttpRequest();
14.14         }
15.15
16.16         public int Order
17.17         {
18.18             get { return 1; }
19.19         }
20.20     }
1.IDependencyRegistrar就是我們上面所說的接口,ContainerTypeFinder類當中的FindClassesOfType()方法會搜尋所有實現該接口的類。實現的註冊工作在Register()方法中完成。<br>接着,封裝一個方法完成所有的Autofac註冊工作,同時便於在Global中調用:<br>
01.1 public static void InitContainer()
02.2         {
03.3             //autofac 容器
04.4             ContainerBuilder builder = new ContainerBuilder();
05.5             //註冊所有控制器
06.6             builder.RegisterControllers(_typeFinder.GetAssemblies().ToArray());
07.7
08.8             #region 反射 核心
09.9             //通過反射得到繼承IDependencyRegistrar該接口的類成員
10.10             var types = _typeFinder.FindClassesOfType(typeof(IDependencyRegistrar));
11.11             var drInstances = new List<IDependencyRegistrar>();
12.12             //創建實例
13.13             foreach (var drType in types)
14.14                 drInstances.Add((IDependencyRegistrar)Activator.CreateInstance(drType));
15.15             //sort
16.16             drInstances = drInstances.AsQueryable().OrderBy(t => t.Order).ToList();
17.17             //執行Register方法
18.18             foreach (var dependencyRegistrar in drInstances)
19.19                 dependencyRegistrar.Register(builder);
20.20             #endregion
21.21
22.22             //then
23.23            var container = builder.Build();
24.24            DependencyResolver.SetResolver(new AutofacDependencyResolver(container));

最後在Global文件Application_Start()方法中調用上述方法

 1 ContainerManager.InitContainer(); 




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章