C Autofac记录

C Autofac记录一 为什么使用 Autofac Autofac 是 NET 领域最为流行的 IoC 框架之一 传说是速度最快的一个

大家好,欢迎来到IT知识分享网。

一、为什么使用Autofac?

1.3、资源

  • 官方网站:http://autofac.org/
  • GitHub网址:https://github.com/autofac/Autofac
  • 学习资料:Autofac中文文档
二、数据准备

2.1、新建项目(例)

项目名称 项目说明 输出类型 引用项目(简写)
AlXiao.IService 接口 类库
AlXiao.Service 接口实现 类库 IService
AlXiao.AdminWebApi 客户端 .NETWebApi IService、Service

IService下的接口类:

namespace AlXiao.IService { 
    public interface IAccountService { 
    /// <summary> /// 后台程序登陆 /// </summary> /// <param name="UserRequest">后台用户信息</param> /// <returns></returns> Task<ResponseResult> LoginByWeb(tb_adminuser_request UserRequest); } } 

Service下的接口实现类:

namespace AlXiao.Service { 
    public class AccountService: IAccountService { 
    /// <summary> /// 后台程序登陆 /// </summary> /// <param name="UserRequest">后台用户信息</param> /// <returns></returns> public async Task<ResponseResult> LoginByWeb(tb_adminuser_request UserRequest) { 
    try { 
    //自己写登录功能 } catch (Exception ex) { 
    } } } } 
namespace AlXiao.Service { 
    public class AccountService2: IAccountService { 
    /// <summary> /// 后台程序登陆 /// </summary> /// <param name="UserRequest">后台用户信息</param> /// <returns></returns> public async Task<ResponseResult> LoginByWeb(tb_adminuser_request UserRequest) { 
    try { 
    //自己写登录功能 } catch (Exception ex) { 
    } } } } 

2.2、Autofac安装
Client项目右键->管理 NuGet 程序包->Autofac
在这里插入图片描述

三、IoC-注册

3.1、类型注册
a)类型注册:使用RegisterType进行注册

/注册Autofac组件 ContainerBuilder builder = new ContainerBuilder; //注册实现类AccountService,当我们请求IAccountService接口的时候,返回的是类Student的对象。 builder.RegisterType<AccountService>.As<IAccountService> ; //上面这句也可改成下面这句,这样请求AccountService实现了的任何接口的时候,都会返回AccountService对象。 //builder.RegisterType<AccountService>.AsImplementedInterfaces(); IContainer container = builder.Build; //请求IAccountService接口 IAccountService baseAccount= container.Resolve<IAccountService> ; baseAccount.LoginByWeb(model); 

b)类型注册(别名):假如一个接口有多个实现类,可以在注册时起别名。

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)类型注册(枚举):假如一个接口有多个实现类,也可以使用枚举的方式注册。

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、实例注册

ContainerBuilder builder = newContainerBuilder; builder.RegisterInstance <IAccountService>( new AccountService); IContainer container = builder.Build; IAccountService baseAccount= container.Resolve<IAccountService> ; baseAccount.LoginByWeb(model); 

3.3、Lambda注册
a)Lambda注册

ContainerBuilder builder = newContainerBuilder; builder.Register(c => new AccountService).As<IAccountService> ; IContainer container = builder.Build; IAccountService baseAccount= container.Resolve<IAccountService> ; baseAccount.LoginByWeb(model); 

b)Lambda注册(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、程序集注册
如果有很多接口及实现类,假如觉得这种一一注册很麻烦的话,可以一次性全部注册,当然也可以加筛选条件。

ContainerBuilder builder = newContainerBuilder; Assembly assembly = Assembly.Load( "AlXiao.IService"); //实现类所在的程序集名称 builder.RegisterAssemblyTypes(assembly).AsImplementedInterfaces; //常用 //builder.RegisterAssemblyTypes(assembly).Where(t=>t.Name.StartsWith("Service")).AsImplementedInterfaces; //带筛选 //builder.RegisterAssemblyTypes(assembly).Except<School>.AsImplementedInterfaces; //带筛选 IContainer container = builder.Build; //单实现类的用法 IAccountService baseAccount= container.Resolve<IAccountService> ; baseAccount.LoginByWeb(model); //多实现类的用法 IEnumerable<IAccountService> list= container.Resolve<IEnumerable<IAccountService>> ; foreach( var item in list) { 
    item.LoginByWeb(model); } 

3.5、泛型注册

ContainerBuilder builder = new ContainerBuilder; builder.RegisterGeneric(typeof(List<>)).As( typeof(IList<> )); IContainer container = builder.Build; IList <string> list = container.Resolve<IList<string>>; 

3.6、默认注册

ContainerBuilder builder = new ContainerBuilder; //对于同一个接口,后面注册的实现会覆盖之前的实现。 //如果不想覆盖的话,可以用PreserveExistingDefaults,这样会保留原来注册的实现。 builder.RegisterType<AccountService>.As<IAccountService> ; builder.RegisterType <AccountService1>.As<IAccountService>.PreserveExistingDefaults; //指定为非默认值 IContainer container = builder.Build; var s1= container.Resolve<IAccountService> ; s1.LoginByWeb(model); 
四、IoC-注入

4.1、构造函数注入

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"); //实现类所在的程序集名称 builder.RegisterAssemblyTypes(assembly).AsImplementedInterfaces.PropertiesAutowired; //常用 IContainer container = builder.Build; IAccountService s1= container.Resolve<IAccountService> ; s1.LoginByWeb(model); 
五、IOC-事件
ContainerBuilder builder = new ContainerBuilder; builder.RegisterType <AccountService>.As<IAccountService> .OnRegistered(e => Console.WriteLine( "OnRegistered:在注册的时候调用")) .OnPreparing(e => Console.WriteLine( "OnPreparing:在准备创建的时候调用")) .OnActivating(e => Console.WriteLine( "OnActivating:在创建之前调用")) //.OnActivating(e => e.ReplaceInstance(new Student("1000", "Test"))) .OnActivated(e => Console.WriteLine( "OnActivated:在创建之后调用")) .OnRelease(e => Console.WriteLine( "OnRelease:在释放占用的资源之前调用")); using(IContainer container = builder.Build) { 
    IAccountService s1= container.Resolve<IAccountService> ; s1.LoginByWeb(model); } 
六、IoC-生命周期

6.1、Per Dependency
Per Dependency:为默认的生命周期,也被称为”transient”或”factory”,其实就是每次请求都创建一个新的对象。

ContainerBuilder builder = new ContainerBuilder; Assembly assembly = Assembly.Load( "AlXiao.IService"); //实现类所在的程序集名称 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:就是每次都用同一个对象。

ContainerBuilder builder = new ContainerBuilder; Assembly assembly = Assembly.Load( "AlXiao.IService"); //实现类所在的程序集名称 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:同一个Lifetime生成的对象是同一个实例。

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项目右键->管理 NuGet 程序包->Autofac.Configuration及Microsoft.Extensions.Configuration.Xml。
在这里插入图片描述
在这里插入图片描述
7.2、配置文件
新建一个AutofacConfigIoC.xml文件,在其属性的复制到输出目录项下选择始终复制。




<?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> <!--构造函数注入--> <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、测试代码

//加载配置 ContainerBuilder builder = new ContainerBuilder; varconfig = new ConfigurationBuilder; config.AddXmlFile( "AutofacConfigIoC.xml"); varmodule = newConfigurationModule(config.Build); builder.RegisterModule(module); IContainer container = builder.Build; //无注入测试 IAccountService s = container.Resolve<IAccountService> ; s.LoginByWeb(model); //构造函数注入测试 AccountService s= container.Resolve<AccountService> ; s.LoginByWeb(model); //属性注入测试 IAccountService s= container.Resolve<IAccountService> ; s.LoginByWeb(model); 
八、AOP

8.1、组件安装
Client项目右键->管理 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> ///拦截器:需实现IInterceptor接口。 ///</summary> public class CallLogger : IInterceptor { 
    private readonly TextWriter _output; public CallLogger(TextWriter output) { 
    _output = output; } ///<summary> ///拦截方法:打印被拦截的方法--执行前的名称、参数以及执行后的返回结果。 ///</summary> ///<param name="invocation">被拦截方法的信息</param> public void Intercept(IInvocation invocation) { 
    //空白行 _output.WriteLine; //在下一个拦截器或目标方法处理之前的处理 _output.WriteLine($ "调用方法:{invocation.Method.Name}"); if (invocation.Arguments.Length > 0) { 
    _output.WriteLine($ "参数:{string.Join(", ", invocation.Arguments.Select(a => (a ?? "").ToString).ToArray)}"); } //调用下一个拦截器(若存在),直到最终的目标方法(Target Method)。 invocation.Proceed; //获取被代理方法的返回类型 varreturnType = invocation.Method.ReturnType; //异步方法 if (IsAsyncMethod(invocation.Method)) { 
    //Task:返回值是固定类型 if (returnType != null && returnType == typeof(Task)) { 
    //定义一个异步方法来等待目标方法返回的Task asyncTask Continuation => await(Task)invocation.ReturnValue; //Continuation中并没有使用await,所以Continuation就如同步方法一样是阻塞的。 invocation.ReturnValue = Continuation; } //Task<T>:返回值是泛型类型 else { 
    //获取被代理方法的返回类型 varreturnTypeT = invocation.Method.ReflectedType; if (returnTypeT != null) { 
    //获取泛型参数集合,集合中的第一个元素等价于typeof(Class)。 varresultType = invocation.Method.ReturnType.GetGenericArguments[0]; //利用反射获得等待返回值的异步方法 MethodInfo methodInfo = typeof(CallLogger).GetMethod("HandleAsync", BindingFlags.Public | BindingFlags.Instance); //调用methodInfo类的MakeGenericMethod方法,用获得的类型T(<resultType>)来重新构造HandleAsync方法。 varmi = methodInfo.MakeGenericMethod(resultType); //Invoke:使用指定参数调用由当前实例表示的方法或构造函数。 invocation.ReturnValue = mi.Invoke(this, new[] { 
    invocation.ReturnValue }); } } vartype = invocation.Method.ReturnType; varresultProperty = type.GetProperty("Result"); if (resultProperty != null) _output.WriteLine($ "方法结果:{resultProperty.GetValue(invocation.ReturnValue)}"); } //同步方法 else { 
    if (returnType != null && returnType != typeof(void)) _output.WriteLine($ "方法结果:{invocation.ReturnValue}"); } } ///<summary> ///判断是否异步方法 ///</summary> public static bool IsAsyncMethod(MethodInfo method) { 
    return ( method.ReturnType == typeof(Task) || (method.ReturnType.IsGenericType && method.ReturnType.GetGenericTypeDefinition == typeof(Task<>)) ); } ///<summary> ///构造等待返回值的异步方法 ///</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、测试代码
注意:对于以类方式的注入,Autofac Interceptor要求类的方法必须为virtual方法。如AnimalWagging类的Wagging、WaggingAsync(string name)都加了virtual修饰符

ContainerBuilder builder = new ContainerBuilder; //注册拦截器 builder.Register(c => newCallLogger(Console.Out)); builder.Register(c => new CallTester); //动态注入拦截器 //这里定义了两个拦截器,注意它们的顺序。 builder.RegisterType<Student>.As<IStudent>.InterceptedBy( typeof(CallLogger), typeof(CallTester)).EnableInterfaceInterceptors; //这里定义了一个拦截器 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}"); 

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/110498.html

(0)
上一篇 2026-01-31 09:26
下一篇 2026-01-31 09:45

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信