什么是AOP
AOP:Aspect oriented programming 面向切面编程,AOP 是 OOP(面向对象编程)的一种延续。
解决:在不改变原有业务逻辑的情况下,增强横切逻辑代码,根本上解耦合,避免横切逻辑代码重复。
AOP利用一种称为“横切”的技术,剖解开封装的对象内部,并将那些影响了多个类的行为封装到一个可重用模块。
AOP实操
Autofac AOP的使用
基本使用:
安装:
安装Autofac 、安装Autofac.Extras.DynamicProxy
添加拦截器
需要实现接口:IInterceptor
public class LogInterceptor : IInterceptor{// invocation:将要拦截的方法public void Intercept(IInvocation invocation){// 执行日志保留记录Console.WriteLine("---在方法执行前记录日志---");// 执行拦截的方法逻辑invocation.Proceed();Console.WriteLine("---在方法执行后记录日志---");}}
public void Intercept(IInvocation invocation)
{Stopwatch sw = new Stopwatch();sw.Start();invocation.Proceed();sw.Stop();Console.WriteLine("MonitorInterceptor 本次方法共耗时:" + sw.ElapsedMilliseconds);
}
加入拦截器
就在注册IOC的地方,注册类型拦截器就好
builder.RegisterType<LogInterceptor>();builder.Regis terType<MonitorInterceptor>();
在注入类的时候,增加拦截器注入:
1、EnableInterfaceInterceptors:基于接口的拦截器
2、EnableClassInterceptors:基于类的拦截器
builder.RegisterType<MainViewModel>().InterceptedBy(typeof(LogInterceptor)).InterceptedBy(typeof(MonitorInterceptor)).EnableClassInterceptors();
需要在所需要拦截器的方法上增加virtual修饰--MainViewModel(注入的需要拦截的类)中
public virtual void DoExport()
{Console.WriteLine("触发了MainViewModel中的Export方法");
}
public virtual void DoSave(string args)
{Thread.Sleep(10);Console.WriteLine("触发了MainViewModel中的Save方法");
}
效果:
可以发现,我写的log是在方法执行前执行的,但是并没有在业务逻辑层写写对应的代码,就在IOC中加入拦截器。
AOP基本思想
动态代理--核心逻辑
static T CreateInstanceWithProxy<T>()
{// 创建动态程序集和模块AssemblyName assemblyName = new AssemblyName("DynamicAssembly");AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("DynamicModule");// 创建一个新的类,并让它继承自ParentClassTypeBuilder typeBuilder = moduleBuilder.DefineType(typeof(T).Name + "__DynamicClass__",TypeAttributes.Public,typeof(T));// 定义要重写的方法MethodInfo[] mis = typeof(T).GetMethods();foreach (MethodInfo mi in mis){Type[] param_types = mi.GetParameters().Select(p => p.ParameterType).ToArray();MethodBuilder methodBuilder = typeBuilder.DefineMethod(mi.Name,// "Logout",MethodAttributes.Public | MethodAttributes.Virtual,mi.ReturnType, //typeof(void),param_types // Type.EmptyTypes);// 获取方法的IL生成器ILGenerator ilGenerator = methodBuilder.GetILGenerator();// 编写方法体指令ilGenerator.Emit(OpCodes.Ldstr, $"[{mi.Name}] 方法执行前--Hello from dynamic method!");ilGenerator.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }));ilGenerator.Emit(OpCodes.Ldarg_0);// 加载this指针if (param_types.Length > 0){ilGenerator.Emit(OpCodes.Ldarg_1);// 加载参数input}ilGenerator.Emit(OpCodes.Call, mi); // 调用基类的方法//ilGenerator.EmitWriteLine("DynamicClass.MethodToOverride");ilGenerator.Emit(OpCodes.Ldstr, $"[{mi.Name}] 方法执行后--Hello from dynamic method!");ilGenerator.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }));ilGenerator.Emit(OpCodes.Ret);}// 创建类型Type dynamicType = typeBuilder.CreateTypeInfo().AsType();// 创建类的实例并调用重写的方法 创建代理类型T instance = (T)Activator.CreateInstance(dynamicType);return instance;
}