程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> ASP.NET >> 關於ASP.NET >> ASP.NET MVC Controller激活系統詳解:IoC的應用[上篇]

ASP.NET MVC Controller激活系統詳解:IoC的應用[上篇]

編輯:關於ASP.NET

所謂控制反轉(IoC: Inversion Of Control)簡單地說就是應用本身不負責依賴對象的創建和維護,而交給一個外部容器來負責。這樣控制權就由應用轉移到了外部IoC容器,控制權就實現了所謂的反轉。比如在類型A中需要使用類型B的實例,而B實例的創建並不由A來負責,而是通過外部容器來創建。通過IoC的方式是實現針對目標Controller的激活具有重要的意義。

一、從Unity來認識IoC

有時我們又將IoC稱為依賴注入(DI: Dependency Injection)。所謂依賴注入,就是由外部容器在運行時動態地將依賴的對象注入到組件之中。Martin Fowler在那篇著名的文章《Inversion of Control Containers and the Dependency Injection pattern》中將具體依賴注入劃分為三種形式,即構造器注入、屬性(設置)注入和接口注入,而我個人習慣將其劃分為一種(類型)匹配和三種注入:

類型匹配(Type Matching):雖然我們通過接口(或者抽象類)來進行服務調用,但是服務本身還是實現在某個具體的服務類型中,這就需要某個類型注冊機制來解決服務接口和服務類型之間的匹配關系;

構造器注入(Constructor Injection):IoC容器會智能地選擇選擇和調用適合的構造函數以創建依賴的對象。如果被選擇的構造函數具有相應的參數,IoC容器在調用構造函數之前解析注冊的依賴關系並自行獲得相應參數對象;

屬性注入(Property Injection):如果需要使用到被依賴對象的某個屬性,在被依賴對象被創建之後,IoC容器會自動初始化該屬性;

方法注入(Method Injection):如果被依賴對象需要調用某個方法進行相應的初始化,在該對象創建之後,IoC容器會自動調用該方法。

開源社區具有很有流行的IoC框架,比如Castle Windsor、Unity、Spring.NET、StructureMap和Ninject等。Unity是微軟Patterns & Practices部門開發的一個輕量級的IoC框架。該項目在Codeplex上的地址為http://unity.codeplex.com/, 你可以下載相應的安裝包和開發文檔。Unity的最新版本為2.1。出於篇幅的限制,我不可能對Unity進行前面的介紹,但是為了讓讀者了解IoC在Unity中的實現,我寫了一個簡單的程序。

我們創建一個控制台程序,定義如下幾個接口(IA、IB、IC和ID)和它們各自的實現類(A、B、C、D)。在類型A中定義了3個屬性B、C和D,其類型分別為接口IB、IC和ID。其中屬性B在構在函數中被初始化,以為著它會以構造器注入的方式被初始化;屬性C上應用了DependencyAttribute特性,意味著這是一個需要以屬性注入方式被初始化的依賴屬性;屬性D則通過方法Initialize初始化,該方法上應用了特性InjectionMethodAttribute,意味著這是一個注入方法在A對象被IoC容器創建的時候會被自動調用。

   1: namespace UnityDemo
2: {
3: public interface IA { }
4: public interface IB { }
5: public interface IC { }
6: public interface ID {}
7:
8: public class A : IA
9: {
10: public IB B { get; set; }
11: [Dependency]
12: public IC C { get; set; }
13: public ID D { get; set; }
14:
15: public A(IB b)
16: {
17: this.B = b;
18: }
19: [InjectionMethod]
20: public void Initialize(ID d)
21: {
22: this.D = d;
23: }
24: }
25: public class B: IB{}
26: public class C: IC{}
27: public class D: ID{}
28: }

然後我們為該應用添加一個配置文件,並定義如下一段關於Unity的配置。這段配置定義了一個名稱為defaultContainer的Unity容器,並在其中完成了上面定義的接口和對應實現類之間映射的類型匹配。

   1: <configuration>
2: <configSections>
3: <section name="unity"
4: type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,
5: Microsoft.Practices.Unity.Configuration"/>
6: </configSections>
7: <unity>
8: <containers>
9: <container name="defaultContainer">
10: <register type="UnityDemo.IA, UnityDemo" mapTo="UnityDemo.A, UnityDemo"/>
11: <register type="UnityDemo.IB, UnityDemo" mapTo="UnityDemo.B, UnityDemo"/>
12: <register type="UnityDemo.IC, UnityDemo" mapTo="UnityDemo.C, UnityDemo"/>
13: <register type="UnityDemo.ID, UnityDemo" mapTo="UnityDemo.D, UnityDemo"/>
14: </container>
15: </containers>
16: </unity>
17: </configuration>

最後在Main方法中創建一個代表IoC容器的UnityContainer對象,並加載配置信息對其進行初始化。然後調用它的泛型的Resolve方法創建一個實現了泛型接口IA的對象。最後將返回對象轉變成類型A,並檢驗其B、C和D屬性是否是空。

   1: static void Main(string[] args)
2: {
3: IUnityContainer container = new UnityContainer();
4: UnityConfigurationSection configuration = ConfigurationManager.GetSection(UnityConfigurationSection.SectionName)
5: as UnityConfigurationSection;
6: configuration.Configure(container, "defaultContainer");
7: A a = container.Resolve<IA>() as A;
8: if (null != a)
9: {
10: Console.WriteLine("a.B == null ? {0}", a.B == null ? "Yes" : "No");
11: Console.WriteLine("a.C == null ? {0}", a.C == null ? "Yes" : "No");
12: Console.WriteLine("a.D == null ? {0}", a.D == null ? "Yes" : "No");
13: }
14: }

從如下給出的執行結果我們可以得到這樣的結論:通過Resolve<IA>方法返回的是一個類型為A的對象,該對象的三個屬性被進行了有效的初始化。這個簡單的程序分別體現了接口注入(通過相應的接口根據配置解析出相應的實現類型)、構造器注入(屬性B)、屬性注入(屬性C)和方法注入(屬性D)。[源代碼從這裡下載]

   1: a.B == null ? No
2: a.C == null ? No
3: a.D == null ? No

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved