动态方法拦截(AOP)的N种解决方案

本文探讨了AOP中的动态方法拦截,包括IL Emit(接口和虚方法)、方法替换(跳转)、RealProxy/TransparentProxy和DispatchProxy四种方案。通过示例代码详细解释了每种方法的工作原理和应用,旨在展示不同方案下的方法拦截如何实现。
摘要由CSDN通过智能技术生成

AOP的本质是方法拦截(将针对目标方法调用劫持下来,进而执行执行的操作),至于方法拦截的实现方案,不外乎两种代码注入类型,即编译时的静态注入和运行时的动态注入,本篇文章列出了几种常用的动态注入方案。这篇文章的目标并不是提供完整的AOP框架的解决方案,而是说明各种解决方案后面的原理,所以我们提供的实例代码会尽可能简单。为了确定拦截操作是否执行,我们定义了如下这个Indicator类型,我们的拦截操作会将其静态属性Injected属性设置为True,我们演示的代码最终通过这个属性来确定拦截是否成功。

public static class Indicator
{ 
    public static bool Injected { get; set; }
}

一、IL Emit(接口)

IL Emit是实现AOP的首选方案。如果方法调用时针对接口完成,我们可以生成一个代理类型来封装对象,并且这个代理类型同时实现目标接口,那么只要我们能够将针对目标对象的方法调用转换成针对代理对象的调用,就能实现针对目标对象的方法拦截。举个简单的例子,Foobar实现了IFoobar接口,如果我们需要拦截接口方法Invoke,我们可以生成一个FoobarProxy类型。如代码片段所示,FoobarProxy封装了一个IFoobar对象,并实现了IFoobar接口。在实现的Invoke方法中,它在调用封装对象的同名方法之前率先执行了拦截操作。

public interface IFoobar
{
    int Invoke();
}

public class Foobar : IFoobar
{
    public int Invoke() => 1;
}

public class FoobarProxy : IFoobar
{
    private readonly IFoobar _target;
    public FoobarProxy(IFoobar target)=>_target = target 
    public int Invoke()
    {
        Indicator.Injected = true;
        return _target.Invoke();
    }
}

上述的这个FoobarProxy类型就可以按照如下的方式利用GenerateProxyClass方法来生成。在Main方法中,我们创建一个Foobar对象,让据此创建这个动态生成的FoobarProxy,当该对象的Invoke方法执行的时候,我们期望的拦截操作自然会自动执行。

class Program
{
    static void Main(string[] args)
    {
        var foobar = new Foobar();
        var proxy = (IFoobar)Activator.CreateInstance(GenerateProxyClass(), foobar);

        Debug.Assert(Indicator.Injected == false);
        Debug.Assert(proxy.Invoke() == 1);
        Debug.Assert(Indicator.Injected == true);
    }

    static Type GenerateProxyClass()
    {
        var assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("Proxy"), AssemblyBuilderAccess.Run);
        var moduleBuilder = assemblyBuilder.DefineDynami
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值