C# Autofac的具體使用
一、為什么使用Autofac?
Autofac是.NET領(lǐng)域最為流行的IoC框架之一,傳說是速度最快的一個(gè)。
1.1、性能
有人專門做了測(cè)試:
1.2、優(yōu)點(diǎn)
1)與C#語言聯(lián)系很緊密。C#里的很多編程方式都可以為Autofac使用,例如可以使用Lambda表達(dá)式注冊(cè)組件。
2)較低的學(xué)習(xí)曲線。學(xué)習(xí)它非常的簡(jiǎn)單,只要你理解了IoC和DI的概念以及在何時(shí)需要使用它們。
3)支持JSON/XML配置。
4)自動(dòng)裝配。
5)與Asp.Net MVC集成。
6)微軟的Orchad開源程序使用的就是Autofac,可以看出它的方便和強(qiáng)大。
1.3、資源
- 官方網(wǎng)站:http://autofac.org/
- GitHub網(wǎng)址:https://github.com/autofac/Autofac
- 學(xué)習(xí)資料:Autofac中文文檔
二、數(shù)據(jù)準(zhǔn)備
2.1、新建項(xiàng)目(例)
項(xiàng)目名稱 | 項(xiàng)目說明 | 輸出類型 | 引用項(xiàng)目(簡(jiǎn)寫) |
---|---|---|---|
AlXiao.IService | 接口 | 類庫 | |
AlXiao.Service | 接口實(shí)現(xiàn) | 類庫 | IService |
AlXiao.AdminWebApi | 客戶端 | .NETWebApi | IService、Service |
IService下的接口類:
namespace AlXiao.IService { public interface IAccountService { /// <summary> /// 后臺(tái)程序登陸 /// </summary> /// <param name="UserRequest">后臺(tái)用戶信息</param> /// <returns></returns> Task<ResponseResult> LoginByWeb(tb_adminuser_request UserRequest); } }
Service下的接口實(shí)現(xiàn)類:
namespace AlXiao.Service { public class AccountService: IAccountService { /// <summary> /// 后臺(tái)程序登陸 /// </summary> /// <param name="UserRequest">后臺(tái)用戶信息</param> /// <returns></returns> public async Task<ResponseResult> LoginByWeb(tb_adminuser_request UserRequest) { try { //自己寫登錄功能 } catch (Exception ex) { } } } }
namespace AlXiao.Service { public class AccountService2: IAccountService { /// <summary> /// 后臺(tái)程序登陸 /// </summary> /// <param name="UserRequest">后臺(tái)用戶信息</param> /// <returns></returns> public async Task<ResponseResult> LoginByWeb(tb_adminuser_request UserRequest) { try { //自己寫登錄功能 } catch (Exception ex) { } } } }
2.2、Autofac安裝
Client項(xiàng)目右鍵->管理 NuGet 程序包->Autofac
三、IoC-注冊(cè)
3.1、類型注冊(cè)
a)類型注冊(cè):使用RegisterType進(jìn)行注冊(cè)
/注冊(cè)Autofac組件 ContainerBuilder builder = new ContainerBuilder; //注冊(cè)實(shí)現(xiàn)類AccountService,當(dāng)我們請(qǐng)求IAccountService接口的時(shí)候,返回的是類Student的對(duì)象。 builder.RegisterType<AccountService>.As<IAccountService> ; //上面這句也可改成下面這句,這樣請(qǐng)求AccountService實(shí)現(xiàn)了的任何接口的時(shí)候,都會(huì)返回AccountService對(duì)象。 //builder.RegisterType<AccountService>.AsImplementedInterfaces(); IContainer container = builder.Build; //請(qǐng)求IAccountService接口 IAccountService baseAccount= container.Resolve<IAccountService> ; baseAccount.LoginByWeb(model);
b)類型注冊(cè)(別名):假如一個(gè)接口有多個(gè)實(shí)現(xiàn)類,可以在注冊(cè)時(shí)起別名。
ContainerBuilder builder = newContainerBuilder; builder.RegisterType <AccountService>.Named<IAccountService>( "S1"); builder.RegisterType <AccountService2>.Named<IAccountService>( "S2"); IContainer container = builder.Build; var s1= container.ResolveNamed<IAccountService >( "S1"); s1.LoginByWeb(model); var s2 = container.ResolveNamed<IAccountService >( "S2"); s2.LoginByWeb(model);
c)類型注冊(cè)(枚舉):假如一個(gè)接口有多個(gè)實(shí)現(xiàn)類,也可以使用枚舉的方式注冊(cè)。
public enum ServiceType { AccountService, AccountService2 } ContainerBuilder builder = new ContainerBuilder; builder.RegisterType <AccountService>.Keyed<IAccountService> (ServiceType.AccountService); builder.RegisterType <AccountService2>.Keyed<IAccountService> (ServiceType.AccountService2); IContainer container = builder.Build; var s1= container.ResolveKeyed<IAccountService> (ServiceType.AccountService); s1.LoginByWeb(model); var s2= container.ResolveKeyed<IAccountService> (ServiceType.AccountService2); s2.LoginByWeb(model);
3.2、實(shí)例注冊(cè)
ContainerBuilder builder = newContainerBuilder; builder.RegisterInstance <IAccountService>( new AccountService); IContainer container = builder.Build; IAccountService baseAccount= container.Resolve<IAccountService> ; baseAccount.LoginByWeb(model);
3.3、Lambda注冊(cè)
a)Lambda注冊(cè)
ContainerBuilder builder = newContainerBuilder; builder.Register(c => new AccountService).As<IAccountService> ; IContainer container = builder.Build; IAccountService baseAccount= container.Resolve<IAccountService> ; baseAccount.LoginByWeb(model);
b)Lambda注冊(cè)(NamedParameter)
ContainerBuilder builder = newContainerBuilder; builder.Register<IAccountService>((c, p) => { vartype = p.Named<string>("type"); if (type == "S1") { return new AccountService; } else { return new AccountService2; } }).As<IAccountService>; IContainer container = builder.Build; var s1= container.Resolve<IAccountService>(newNamedParameter("type", "S1")); s1.LoginByWeb(model);
3.4、程序集注冊(cè)
如果有很多接口及實(shí)現(xiàn)類,假如覺得這種一一注冊(cè)很麻煩的話,可以一次性全部注冊(cè),當(dāng)然也可以加篩選條件。
ContainerBuilder builder = newContainerBuilder; Assembly assembly = Assembly.Load( "AlXiao.IService"); //實(shí)現(xiàn)類所在的程序集名稱 builder.RegisterAssemblyTypes(assembly).AsImplementedInterfaces; //常用 //builder.RegisterAssemblyTypes(assembly).Where(t=>t.Name.StartsWith("Service")).AsImplementedInterfaces; //帶篩選 //builder.RegisterAssemblyTypes(assembly).Except<School>.AsImplementedInterfaces; //帶篩選 IContainer container = builder.Build; //單實(shí)現(xiàn)類的用法 IAccountService baseAccount= container.Resolve<IAccountService> ; baseAccount.LoginByWeb(model); //多實(shí)現(xiàn)類的用法 IEnumerable<IAccountService> list= container.Resolve<IEnumerable<IAccountService>> ; foreach( var item in list) { item.LoginByWeb(model); }
3.5、泛型注冊(cè)
ContainerBuilder builder = new ContainerBuilder; builder.RegisterGeneric(typeof(List<>)).As( typeof(IList<> )); IContainer container = builder.Build; IList <string> list = container.Resolve<IList<string>>;
3.6、默認(rèn)注冊(cè)
ContainerBuilder builder = new ContainerBuilder; //對(duì)于同一個(gè)接口,后面注冊(cè)的實(shí)現(xiàn)會(huì)覆蓋之前的實(shí)現(xiàn)。 //如果不想覆蓋的話,可以用PreserveExistingDefaults,這樣會(huì)保留原來注冊(cè)的實(shí)現(xiàn)。 builder.RegisterType<AccountService>.As<IAccountService> ; builder.RegisterType <AccountService1>.As<IAccountService>.PreserveExistingDefaults; //指定為非默認(rèn)值 IContainer container = builder.Build; var s1= container.Resolve<IAccountService> ; s1.LoginByWeb(model);
四、IoC-注入
4.1、構(gòu)造函數(shù)注入
ContainerBuilder builder = new ContainerBuilder; builder.RegisterType <AccountService> ; builder.RegisterType <AccountService1>.As<IAccountService> ; IContainer container = builder.Build; AccountService s1= container.Resolve<AccountService> ; s1.LoginByWeb(model);
4.2、屬性注入
ContainerBuilder builder = new ContainerBuilder; Assembly assembly = Assembly.Load( "AlXiao.IService"); //實(shí)現(xiàn)類所在的程序集名稱 builder.RegisterAssemblyTypes(assembly).AsImplementedInterfaces.PropertiesAutowired; //常用 IContainer container = builder.Build; IAccountService s1= container.Resolve<IAccountService> ; s1.LoginByWeb(model);
五、IOC-事件
Autofac在組件生命周期的不同階段,共對(duì)應(yīng)了5個(gè)事件,執(zhí)行順序如下所示:
1.OnRegistered->2.OnPreparing->3.OnActivating->4.OnActivated->5.OnRelease
ContainerBuilder builder = new ContainerBuilder; builder.RegisterType <AccountService>.As<IAccountService> .OnRegistered(e => Console.WriteLine( "OnRegistered:在注冊(cè)的時(shí)候調(diào)用")) .OnPreparing(e => Console.WriteLine( "OnPreparing:在準(zhǔn)備創(chuàng)建的時(shí)候調(diào)用")) .OnActivating(e => Console.WriteLine( "OnActivating:在創(chuàng)建之前調(diào)用")) //.OnActivating(e => e.ReplaceInstance(new Student("1000", "Test"))) .OnActivated(e => Console.WriteLine( "OnActivated:在創(chuàng)建之后調(diào)用")) .OnRelease(e => Console.WriteLine( "OnRelease:在釋放占用的資源之前調(diào)用")); using(IContainer container = builder.Build) { IAccountService s1= container.Resolve<IAccountService> ; s1.LoginByWeb(model); }
六、IoC-生命周期
6.1、Per Dependency
Per Dependency:為默認(rèn)的生命周期,也被稱為"transient"或"factory",其實(shí)就是每次請(qǐng)求都創(chuàng)建一個(gè)新的對(duì)象。
ContainerBuilder builder = new ContainerBuilder; Assembly assembly = Assembly.Load( "AlXiao.IService"); //實(shí)現(xiàn)類所在的程序集名稱 builder.RegisterAssemblyTypes(assembly).AsImplementedInterfaces.PropertiesAutowired.InstancePerDependency; //常用 IContainer container = builder.Build; IAccountService s1= container.Resolve<IAccountService> ; IAccountService s2 = container.Resolve<IAccountService> ; return s1.Equals(s2);
6.2、Single Instance
Single Instance:就是每次都用同一個(gè)對(duì)象。
ContainerBuilder builder = new ContainerBuilder; Assembly assembly = Assembly.Load( "AlXiao.IService"); //實(shí)現(xiàn)類所在的程序集名稱 builder.RegisterAssemblyTypes(assembly).AsImplementedInterfaces.PropertiesAutowired.SingleInstance; //常用 IContainer container = builder.Build; IAccountService s1= container.Resolve<IAccountService> ; IAccountService s2= container.Resolve<IAccountService> ; return ReferenceEquals(s1, s2);
6.3、Per Lifetime Scope
Per Lifetime Scope:同一個(gè)Lifetime生成的對(duì)象是同一個(gè)實(shí)例。
ContainerBuilder builder = new ContainerBuilder; builder.RegisterType <AccountService>.As<IAccountService> .InstancePerLifetimeScope; IContainer container = builder.Build; IAccountService s1= container.Resolve<IAccountService> ; IAccountService s2 = container.Resolve<IAccountService> ; Console.WriteLine(s1.Equals(s2)); using(ILifetimeScope lifetime = container.BeginLifetimeScope) { IAccountService s3 = lifetime.Resolve<IAccountService> ; IAccountService s4 = lifetime.Resolve<IAccountService> ; Console.WriteLine(s3.Equals(s4)); Console.WriteLine(s2.Equals(s3)); }
七、IoC-通過配置文件使用Autofac
7.1、組件安裝
Client項(xiàng)目右鍵->管理 NuGet 程序包->Autofac.Configuration及Microsoft.Extensions.Configuration.Xml。
7.2、配置文件
新建一個(gè)AutofacConfigIoC.xml文件,在其屬性的復(fù)制到輸出目錄項(xiàng)下選擇始終復(fù)制。
<?xml version="1.0" encoding="utf-8" ?> <autofac defaultAssembly="AlXiao.IService"> <!--無注入--> <components name="1001"> <type>AlXiao.IService.AccountService, AlXiao.IService </type> <services name="0"type="AlXiao.IService.IAccountService"/> <injectProperties>true </injectProperties> </components> <components name="1002"> <type>AlXiao.IService.AccountService, AlXiao.IService</type> <services name="0"type="AlXiao.IService.IAccountService2"/> <injectProperties>true </injectProperties> </components> <!--構(gòu)造函數(shù)注入--> <components name="2001"> <type>AlXiao.IService.AccountService, AlXiao.IService</type> <services name="0"type="AlXiao.IService.AccountService, AlXiao.IService"/> <injectProperties>true </injectProperties> </components> <!--屬性注入--> <components name="3001"> <type>AlXiao.IService.AccountService, AlXiao.IService</type> <services name="0"type="AlXiao.IService.IAccountService"/> <injectProperties>true </injectProperties> </components> </autofac>
7.3、測(cè)試代碼
//加載配置 ContainerBuilder builder = new ContainerBuilder; varconfig = new ConfigurationBuilder; config.AddXmlFile( "AutofacConfigIoC.xml"); varmodule = newConfigurationModule(config.Build); builder.RegisterModule(module); IContainer container = builder.Build; //無注入測(cè)試 IAccountService s = container.Resolve<IAccountService> ; s.LoginByWeb(model); //構(gòu)造函數(shù)注入測(cè)試 AccountService s= container.Resolve<AccountService> ; s.LoginByWeb(model); //屬性注入測(cè)試 IAccountService s= container.Resolve<IAccountService> ; s.LoginByWeb(model);
八、AOP
8.1、組件安裝
Client項(xiàng)目右鍵->管理 NuGet 程序包->Autofac.Extras.DynamicProxy。
8.2、拉截器
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; using Castle.DynamicProxy; namespace AlXiao.CommonCore.DTO { ///<summary> ///攔截器:需實(shí)現(xiàn)IInterceptor接口。 ///</summary> public class CallLogger : IInterceptor { private readonly TextWriter _output; public CallLogger(TextWriter output) { _output = output; } ///<summary> ///攔截方法:打印被攔截的方法--執(zhí)行前的名稱、參數(shù)以及執(zhí)行后的返回結(jié)果。 ///</summary> ///<param name="invocation">被攔截方法的信息</param> public void Intercept(IInvocation invocation) { //空白行 _output.WriteLine; //在下一個(gè)攔截器或目標(biāo)方法處理之前的處理 _output.WriteLine($ "調(diào)用方法:{invocation.Method.Name}"); if (invocation.Arguments.Length > 0) { _output.WriteLine($ "參數(shù):{string.Join(", ", invocation.Arguments.Select(a => (a ?? "").ToString).ToArray)}"); } //調(diào)用下一個(gè)攔截器(若存在),直到最終的目標(biāo)方法(Target Method)。 invocation.Proceed; //獲取被代理方法的返回類型 varreturnType = invocation.Method.ReturnType; //異步方法 if (IsAsyncMethod(invocation.Method)) { //Task:返回值是固定類型 if (returnType != null && returnType == typeof(Task)) { //定義一個(gè)異步方法來等待目標(biāo)方法返回的Task asyncTask Continuation => await(Task)invocation.ReturnValue; //Continuation中并沒有使用await,所以Continuation就如同步方法一樣是阻塞的。 invocation.ReturnValue = Continuation; } //Task<T>:返回值是泛型類型 else { //獲取被代理方法的返回類型 varreturnTypeT = invocation.Method.ReflectedType; if (returnTypeT != null) { //獲取泛型參數(shù)集合,集合中的第一個(gè)元素等價(jià)于typeof(Class)。 varresultType = invocation.Method.ReturnType.GetGenericArguments[0]; //利用反射獲得等待返回值的異步方法 MethodInfo methodInfo = typeof(CallLogger).GetMethod("HandleAsync", BindingFlags.Public | BindingFlags.Instance); //調(diào)用methodInfo類的MakeGenericMethod方法,用獲得的類型T(<resultType>)來重新構(gòu)造HandleAsync方法。 varmi = methodInfo.MakeGenericMethod(resultType); //Invoke:使用指定參數(shù)調(diào)用由當(dāng)前實(shí)例表示的方法或構(gòu)造函數(shù)。 invocation.ReturnValue = mi.Invoke(this, new[] { invocation.ReturnValue }); } } vartype = invocation.Method.ReturnType; varresultProperty = type.GetProperty("Result"); if (resultProperty != null) _output.WriteLine($ "方法結(jié)果:{resultProperty.GetValue(invocation.ReturnValue)}"); } //同步方法 else { if (returnType != null && returnType != typeof(void)) _output.WriteLine($ "方法結(jié)果:{invocation.ReturnValue}"); } } ///<summary> ///判斷是否異步方法 ///</summary> public static bool IsAsyncMethod(MethodInfo method) { return ( method.ReturnType == typeof(Task) || (method.ReturnType.IsGenericType && method.ReturnType.GetGenericTypeDefinition == typeof(Task<>)) ); } ///<summary> ///構(gòu)造等待返回值的異步方法 ///</summary> ///<typeparam name="T"></typeparam> ///<param name="task"></param> ///<returns></returns> public async Task<T> HandleAsync<T>(Task<T> task) { vart = awaittask; returnt; } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Castle.DynamicProxy; namespace AlXiao.CommonCore.DTO { public class CallTester : IInterceptor { public void Intercept(IInvocation invocation) { Console.WriteLine("啥也不干"); invocation.Proceed; Console.WriteLine("也不干啥"); } } }
8.3、測(cè)試代碼
注意:對(duì)于以類方式的注入,Autofac Interceptor要求類的方法必須為virtual方法。如AnimalWagging類的Wagging、WaggingAsync(string name)都加了virtual修飾符
ContainerBuilder builder = new ContainerBuilder; //注冊(cè)攔截器 builder.Register(c => newCallLogger(Console.Out)); builder.Register(c => new CallTester); //動(dòng)態(tài)注入攔截器 //這里定義了兩個(gè)攔截器,注意它們的順序。 builder.RegisterType<Student>.As<IStudent>.InterceptedBy( typeof(CallLogger), typeof(CallTester)).EnableInterfaceInterceptors; //這里定義了一個(gè)攔截器 builder.RegisterType<AnimalWagging>.InterceptedBy( typeof(CallLogger)).EnableClassInterceptors; builder.RegisterType <Dog>.As<IAnimalBark> ; IContainer container = builder.Build; IStudent student = container.Resolve<IStudent> ; student.Add( "1003", "Kobe"); AnimalWagging animal = container.Resolve<AnimalWagging> ; animal.Wagging; Task <string> task = animal.WaggingAsync( "哈士奇"); Console.WriteLine($ "{task.Result}");
到此這篇關(guān)于C# Autofac的具體使用的文章就介紹到這了,更多相關(guān)C# Autofac內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C#多態(tài)的三種實(shí)現(xiàn)方式(小結(jié))
這篇文章主要介紹了C#多態(tài)的三種實(shí)現(xiàn)方式(小結(jié)),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03C#使用Data?Annotations進(jìn)行手動(dòng)數(shù)據(jù)驗(yàn)證
這篇文章介紹了C#使用Data?Annotations進(jìn)行手動(dòng)數(shù)據(jù)驗(yàn)證的方法,文中通過示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-06-06c#的時(shí)間日期操作示例分享(c#獲取當(dāng)前日期)
這篇文章主要介紹了c#的時(shí)間日期操作示例,在給定時(shí)間戳返回指定的時(shí)間格式和獲取當(dāng)前時(shí)間方法,需要的朋友可以參考下2014-03-03c#批量抓取免費(fèi)代理并且驗(yàn)證有效性的實(shí)戰(zhàn)教程
突破反爬蟲限制的方法之一就是多用幾個(gè)代理IP,下面這篇文章主要給大家介紹了關(guān)于利用c#批量抓取免費(fèi)代理并且驗(yàn)證有效性的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下2018-07-07C#中使用ADOMD.NET查詢多維數(shù)據(jù)集的實(shí)現(xiàn)方法
這篇文章主要介紹了C#中使用ADOMD.NET查詢多維數(shù)據(jù)集的實(shí)現(xiàn)方法,詳細(xì)講述了C#中使用ADOMD.NET查詢多維數(shù)據(jù)集的原理與實(shí)現(xiàn)技巧,需要的朋友可以參考下2014-10-10C#實(shí)現(xiàn)char字符數(shù)組與字符串相互轉(zhuǎn)換的方法
這篇文章主要介紹了C#實(shí)現(xiàn)char字符數(shù)組與字符串相互轉(zhuǎn)換的方法,結(jié)合實(shí)例形式簡(jiǎn)單分析了C#字符數(shù)組轉(zhuǎn)字符串及字符串轉(zhuǎn)字符數(shù)組的具體實(shí)現(xiàn)技巧,需要的朋友可以參考下2017-02-02