Autofac類型注冊
類型注冊簡單的從字面去理解就可以了,不必復雜化,只是注冊的手段比較豐富。
(一)類型/泛型注冊
builder.RegisterType<Class1>();
這種簡單較常用,但缺點是注冊的類型必須在當前項目或被當前項目引用,因為使用泛型,必須類型明確。
針對這點,還有一種通過Type對象進行注冊的方式:
//字符串為類型完全名稱 builder.RegisterType(Type.GetType("AutofacBlog.Class_1"));
使用這種方式進行類型注冊,被注冊的類型可以不是被直接引用,但類型所在的程序集必須被加載。
這種注冊方式在有插件或類似需要動態加載程序集的情況下使用,通過掃描程序集,獲取一些滿足指定條件的類型,來進行注冊。
(二)程序集批量注冊
類型注冊中提到了通過掃描程序集來獲取部分類型進行注冊。Autofac對此提供了一個方便的方式,可以直接通過程序集來篩選類型注冊:
//獲取當前應用程序加載程序集(C/S應用中使用) var assembly = Assembly.GetExecutingAssembly(); var builder = new ContainerBuilder(); builder.RegisterAssemblyTypes(assembly); //注冊所有程序集類定義的非靜態類型
代碼通過RegisterAssemblyTypes方法,將assembly中所有自定義的非靜態類型都注冊到Autofac中,后面可以使用IContainer對象獲取所有該程序集中自定義的類型對象。
這種方式達到了批量的效果,但是通常,我們並不需要把所有的類型都進行注冊,所以Autofac提供了幾種過濾方式:
builder.RegisterAssemblyTypes(assembly) .Where(type => type.Namespace.Equals("IocAutofac.Example")); //條件判斷
這種方式相信大家都比較熟悉,Where+lambda的方式來進行條件判斷,lambda參數為Type類型,也就是程序集中的type。
builder.RegisterAssemblyTypes(assembly) .Except<Program>(); //排除Program類型
這種方式用來排除指定類型的注冊,當排除的個例比較少時,會比較適用。Except還有另一種用法,但是用法比較復雜,在此不進行介紹。
builder.RegisterAssemblyTypes(assembly) .InNamespace("IocAutofac.Example"); //類型在IocAutofac.Example命名空間中
被注冊的類型需要在指定命名空間中。
builder.RegisterAssemblyTypes(assembly) .InNamespaceOf<Program>(); //類型在Program所在的命名空間中*/
這種方式與上面一種方式比較相似,也是用來判斷命名空間的,這種方式是根據類型來獲取命名空間。
通過這種方式,我們可以對程序集中的類型進行批量注冊,類型/泛型方式在被注冊類型較少的情況下還是不錯的,但當被注冊類型很多的時候,一個一個的手寫注冊會顯得很無力,這時候就是程序集批量注冊顯威的時候了。
(三)Lambda注冊
上面講到的兩種方式都是通過類型進行直接注冊的,這種注冊方式,在獲取時,會直接通過構造函數new出對象,不會做更多的操作。
有時,我們希望能夠在獲取對象時能夠自動的做更多的事情時,我們可以通過Lambda注冊來解決:
builder.Register(cc => { var clas1 = new Class_1(); while (clas1.Id.ToString().Contains("a")) { clas1.Id = Guid.NewGuid(); } return clas1; });
上述代碼,實際注冊了Class_1類型,因為最后返回的對象類型為Class_1。
Register方法接收了一個lambda表達式作為參數,在lambda表達式中,我們可以做很多事,包括一些屬性注入(后續說明)、方法注入(后續說明)、條件判斷等等。
(四)實例注冊
var clas1 = new Class_1(); clas1.Id = Guid.Empty; builder.RegisterInstance(clas1);
通過RegisterInstance進行實例注冊,進行實例注冊時,我們需要注意,實例注冊可以作為一種單例注冊的方式,也就是在后面通過Autofac獲取Class_1對象時,獲取到的是注冊時的那個對象。並且,如果一個在某處修改了該對象,其他地方再獲取時,獲取到的就是修改后的對象。
(五)Module注冊
在日常開發中,可能不同開發會負責不同的模塊進行單獨開發。在開發過程中,不同模塊可能都有自己的類型需要注冊到autofac中,但是如果每個人在注冊時,都去修改一個指定地方的代碼,這在進行代碼合並時,是令人痛苦的。更好的方式是每個開發不同的模塊都有自己指定的類型注冊區域,這樣,在代碼合並時,會減少很多代碼沖突。
對於這種方式,Autofac已經為我們提供了:
class Program { static void Main(string[] args) { var builder = new ContainerBuilder(); builder.RegisterModule<ModuleA>(); //這兩種注冊方式達到的效果都一樣 builder.RegisterModule(new ModuleB()); IContainer container = builder.Build(); Class_1 clas1 = container.Resolve<Class_1>(); Class_2 clas2 = container.Resolve<Class_2>(); Console.WriteLine(clas1.Id); Console.WriteLine(clas2.ToString()); Console.Write("Press any key to continue..."); Console.ReadKey(); } } class ModuleA : Module { protected override void Load(ContainerBuilder builder) { builder.RegisterType<Class_1>(); } } class ModuleB : Module { protected override void Load(ContainerBuilder builder) { builder.RegisterType<Class_2>(); } }
兩個繼承自Module類的類:ModuleA、ModuleB重寫了父類的Load方法並在load方法中注冊了Class_1與Class_2類型,然后在主程序中,通過RegisterModule對Module進行注冊。不同的開發就可以各自創建一個類繼承自Module,然后重寫Load方法,在Load方法進行自己的類型注冊,最后再進行Module的統一注冊。
Module注意說明
實際上,RegisterModule需要的參數,並不是繼承自Module類的,而是實現了IModule接口的類,而Module也是實現了IModule接口的。也就是我們也可以寫一個實現了IModule接口的類型,然后在RegisterModule時傳入。但是一般我們直接去繼承Module就好了,這種方式比較簡單方便,實現IModule的方式更為復雜,當然,功能也更多,在此就不進行介紹了。
程序集Module注冊
Module注冊,為多人開發提供了一種方便的注冊方式,但這種方式還是會需要手動注冊Module,如果Module過多,Module注冊代碼也會顯得多而雜,當然,可以通過人工管理來控制Module的量。但是Autofac還提供了一種更方便的方式且對於類似Orchard的模塊開發(子模塊與主模塊無引用關系,通過程序集加載方式來加載子模塊)或是插件開發,我們沒辦法通過Registerodule來注冊無直接引用關系的Module。
對於上述的情況,Autofac提供了很好的方式來解決:
var builder = new ContainerBuilder(); var assembly = Assembly.GetExecutingAssembly(); builder.RegisterAssemblyModules(assembly);
代碼注冊assembly程序集中所有實現了IModule接口的類型,這樣只需要取出所有程序集通過RegisterAssemblyModules進行一次性注冊,就可以自動注冊所有Module了。
RegisterAssemblyModule還可以指定一個泛型類型:
builder.RegisterAssemblyModules<ModuleA>(assembly);
這樣注冊是指定只注冊assembly程序集中繼承自ModuleA的Module。
文章來源: http://www.cnblogs.com/ancupofcoffee/p/5007649.html
備注:類型注冊只是一部分,個人認為一般不會注冊一個類型然后直接去取這個類型的實例,因為沒有那個必要。autofac常用的應用場景應該是像簡單實例篇中所描述的場景,所以有了類型關聯這一篇。