AOP思想

什么是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");

    // 创建一个新的类,并让它继承自ParentClass
    TypeBuilder 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;
}
  • 6
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值