当前位置:
首页 > 编程开发 > Python基础教程 >
-
python基础教程之C# Autofac学习笔记(2)
本站最新发布 Python从入门到精通|Python基础教程
试听地址 https://www.xin3721.com/eschool/pythonxin3721/
(List<>)).As(typeof(IList<>)); IContainer container = builder.Build(); IList<string> list = container.Resolve<IList<string>>();
试听地址 https://www.xin3721.com/eschool/pythonxin3721/
(List<>)).As(typeof(IList<>)); IContainer container = builder.Build(); IList<string> list = container.Resolve<IList<string>>();
3.6、默认注册

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

ContainerBuilder builder = new ContainerBuilder(); builder.RegisterType<AnimalWagging>(); builder.RegisterType<Dog>().As<IAnimalBark>(); IContainer container = builder.Build(); AnimalWagging animal = container.Resolve<AnimalWagging>(); animal.Wagging();
4.2、属性注入

ContainerBuilder builder = new ContainerBuilder(); Assembly assembly = Assembly.Load("LinkTo.Test.Autofac.Service"); //实现类所在的程序集名称 builder.RegisterAssemblyTypes(assembly).AsImplementedInterfaces().PropertiesAutowired(); //常用 IContainer container = builder.Build(); ISchool school = container.Resolve<ISchool>(); school.LeaveSchool();
五、IoC-事件
Autofac在组件生命周期的不同阶段,共对应了5个事件,执行顺序如下所示:
1.OnRegistered->2.OnPreparing->3.OnActivating->4.OnActivated->5.OnRelease

ContainerBuilder builder = new ContainerBuilder(); builder.RegisterType<Student>().As<IStudent>() .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()) { IStudent student = container.Resolve<IStudent>(); student.Add("1001", "Hello"); }
六、IoC-生命周期
6.1、Per Dependency
Per Dependency:为默认的生命周期,也被称为"transient"或"factory",其实就是每次请求都创建一个新的对象。

ContainerBuilder builder = new ContainerBuilder(); Assembly assembly = Assembly.Load("LinkTo.Test.Autofac.Service"); //实现类所在的程序集名称 builder.RegisterAssemblyTypes(assembly).AsImplementedInterfaces().PropertiesAutowired().InstancePerDependency(); //常用 IContainer container = builder.Build(); ISchool school1 = container.Resolve<ISchool>(); ISchool school2 = container.Resolve<ISchool>(); Console.WriteLine(school1.Equals(school2));
6.2、Single Instance
Single Instance:就是每次都用同一个对象。

ContainerBuilder builder = new ContainerBuilder(); Assembly assembly = Assembly.Load("LinkTo.Test.Autofac.Service"); //实现类所在的程序集名称 builder.RegisterAssemblyTypes(assembly).AsImplementedInterfaces().PropertiesAutowired().SingleInstance(); //常用 IContainer container = builder.Build(); ISchool school1 = container.Resolve<ISchool>(); ISchool school2 = container.Resolve<ISchool>(); Console.WriteLine(ReferenceEquals(school1, school2));
6.3、Per Lifetime Scope
Per Lifetime Scope:同一个Lifetime生成的对象是同一个实例。

ContainerBuilder builder = new ContainerBuilder(); builder.RegisterType<School>().As<ISchool>().InstancePerLifetimeScope(); IContainer container = builder.Build(); ISchool school1 = container.Resolve<ISchool>(); ISchool school2 = container.Resolve<ISchool>(); Console.WriteLine(school1.Equals(school2)); using (ILifetimeScope lifetime = container.BeginLifetimeScope()) { ISchool school3 = lifetime.Resolve<ISchool>(); ISchool school4 = lifetime.Resolve<ISchool>(); Console.WriteLine(school3.Equals(school4)); Console.WriteLine(school2.Equals(school3)); }
七、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="LinkTo.Test.Autofac.IService"> <!--无注入--> <components name="1001"> <type>LinkTo.Test.Autofac.Service.Student, LinkTo.Test.Autofac.Service</type> <services name="0" type="LinkTo.Test.Autofac.IService.IStudent" /> <injectProperties>true</injectProperties> </components> <components name="1002"> <type>LinkTo.Test.Autofac.Service.Dog, LinkTo.Test.Autofac.Service</type> <services name="0" type="LinkTo.Test.Autofac.IService.IAnimalBark" /> <injectProperties>true</injectProperties> </components> <!--构造函数注入--> <components name="2001"> <type>LinkTo.Test.Autofac.Service.AnimalWagging, LinkTo.Test.Autofac.Service</type> <services name="0" type="LinkTo.Test.Autofac.Service.AnimalWagging, LinkTo.Test.Autofac.Service" /> <injectProperties>true</injectProperties> </components> <!--属性注入--> <components name="3001"> <type>LinkTo.Test.Autofac.Service.School, LinkTo.Test.Autofac.Service</type> <services name="0" type="LinkTo.Test.Autofac.IService.ISchool" /> <injectProperties>true</injectProperties> </components> </autofac>
7.3、测试代码

//加载配置 ContainerBuilder builder = new ContainerBuilder(); var config = new ConfigurationBuilder(); config.AddXmlFile("AutofacConfigIoC.xml"); var module = new ConfigurationModule(config.Build()); builder.RegisterModule(module); IContainer container = builder.Build(); //无注入测试 IStudent student = container.Resolve<IStudent>(); student.Add("1002", "World"); //构造函数注入测试 AnimalWagging animal = container.Resolve<AnimalWagging>(); animal.Wagging(); //属性注入测试 ISchool school = container.Resolve<ISchool>(); school.LeaveSchool();
八、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 LinkTo.Test.Autofac.Client { /// <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(); //获取被代理方法的返回类型 var returnType = invocation.Method.ReturnType; //异步方法 if (IsAsyncMethod(invocation.Method)) { //Task:返回值是固定类型 if (returnType != null && returnType == typeof(Task)) { //定义一个异步方法来等待目标方法返回的Task async Task Continuation() => await (Task)invocation.ReturnValue; //Continuation()中并没有使用await,所以Continuation()就如同步方法一样是阻塞的。 invocation.ReturnValue = Continuation(); } //Task<T>:返回值是泛型类型 else { //获取被代理方法的返回类型 var returnTypeT = invocation.Method.ReflectedType; if (returnTypeT != null) { //获取泛型参数集合,集合中的第一个元素等价于typeof(Class)。 var resultType = invocation.Method.ReturnType.GetGenericArguments()[0]; //利用反射获得等待返回值的异步方法 MethodInfo methodInfo = typeof(CallLogger).GetMethod("HandleAsync", BindingFlags.Public | BindingFlags.Instance); //调用methodInfo类的MakeGenericMethod()方法,用获得的类型T(<resultType>)来重新构造HandleAsync()方法。 var mi = methodInfo.MakeGenericMethod(resultType); //Invoke:使用指定参数调用由当前实例表示的方法或构造函数。 invocation.ReturnValue = mi.Invoke(this, new[] { invocation.ReturnValue }); } } var type = invocation.Method.ReturnType; var resultProperty = 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) { var t = await task; return t; } } }

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Castle.DynamicProxy; namespace LinkTo.Test.Autofac.Client { 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 => new CallLogger(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}");