天天看點

.NET 下基于動态代理的 AOP 架構實作揭秘

.NET 下基于動态代理的 AOP 架構實作揭秘

Intro#

之前基于 Roslyn 實作了一個簡單的條件解析引擎,想了解的可以看這篇文章 

https://www.cnblogs.com/weihanli/p/roslyn-based-condition-eval-engine.html

執行過程中會根據條件的不同會在運作時建立一個類,每一次建立都會生成一個新的程式集,我覺得這樣實作的話可能會導緻加載的程式集越來越多,雖然目前我們的使用場景下不會有很多,而且相同的條件隻會生成一次,還是覺得這樣不是特别好,此時想起來了一些 AOP 架構,Aspect.Core/Castle/DispatchProxy ,他們這些 AOP 架構會生成一些代碼類,好像也沒有生成很多額外的程式集,于是打算看看這些 AOP 架構的實作,看看它們是如何生成動态代理類的

動态代理實作原理#

看了這三個 AOP 架構的實作代碼之後,實作原理基本都是一樣的

都是通過建立一個 DynamicAssembly 之後在這個 DynamicAssemly 中建立要動态生成代理類,通過 Emit 建立要生成動态代理類的方法/屬性等

來個小示例#

多說不如來點代碼示例:

Copy

internal class ProxyUtil

{

private const string ProxyAssemblyName = "Aop.DynamicGenerated";
private static readonly ModuleBuilder _moduleBuilder;
private static readonly ConcurrentDictionary<string, Type> _proxyTypes = new ConcurrentDictionary<string, Type>();

static ProxyUtil()
{
    // 定義一個動态程式集
    var asmBuilder = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName(ProxyAssemblyName), AssemblyBuilderAccess.Run);
    // 建立一個動态子產品,後面建立動态代理類通過這個來建立
    _moduleBuilder = asmBuilder.DefineDynamicModule("Default");
}

public static Type CreateInterfaceProxy(Type interfaceType)
{
    var proxyTypeName = $"{ProxyAssemblyName}.{interfaceType.FullName}";
    var type = _proxyTypes.GetOrAdd(proxyTypeName, name =>
    {
        // 定義要建立的類型,并實作指定類型接口
        var typeBuilder = _moduleBuilder.DefineType(proxyTypeName, TypeAttributes.Public, typeof(object), new[] { interfaceType });
        // 定義一個預設的構造方法
        typeBuilder.DefineDefaultConstructor(MethodAttributes.Public);
        // 擷取接口中定義的方法
        var methods = interfaceType.GetMethods(BindingFlags.Instance | BindingFlags.Public);
        foreach (var method in methods)
        {
            // 在動态類中定義方法,方法名稱,傳回值和簽名與接口方法保持一緻
            var methodBuilder = typeBuilder.DefineMethod(method.Name
                , MethodAttributes.Public | MethodAttributes.Virtual,
                method.CallingConvention,
                method.ReturnType,
                method.GetParameters()
                    .Select(p => p.ParameterType)
                    .ToArray()
                );                

            // 擷取 ILGenerator,通過 Emit 實作方法體
            var ilGenerator = methodBuilder.GetILGenerator();
            ilGenerator.EmitWriteLine($"method [{method.Name}] is invoking...");
            ilGenerator.Emit(OpCodes.Ret);
            
            // 定義方法實作
            typeBuilder.DefineMethodOverride(methodBuilder, method);
        }

        return typeBuilder.CreateType();
    });
    return type;
}           

}

通過上面的定義我們可以建立一個簡單的代理類,然後定義一個 ProxyGenerator 來建立代理

public class ProxyGenerator

public static readonly ProxyGenerator Instance = new ProxyGenerator();

public object CreateInterfaceProxy(Type interfaceType)
{
    var type = ProxyUtil.CreateInterfaceProxy(interfaceType);
    return Activator.CreateInstance(type);
}           

// 定義泛型擴充

public static class ProxyGeneratorExtensions

public static TInterface CreateInterfaceProxy<TInterface>(this ProxyGenerator proxyGenerator) =>
    (TInterface)proxyGenerator.CreateInterfaceProxy(typeof(TInterface));           

使用示例:

var testService = ProxyGenerator.Instance.CreateInterfaceProxy();

testService.Test();

可以看到這個類型就是我們動态建立的一個類型,輸出結果也是我們定義在代理類中的結果

More#

.NET 中的基于動态代理的 AOP 也是這樣實作的,實作的原理大緻就是這樣,這個示例比較簡單還沒有涉及 AOP ,這隻是一個簡單的動态代理示例 ,AOP 隻需要在原始方法執行的邏輯上包裝一層攔截器增加對攔截器的處理和調用即可,暫時還沒實作,後面有機會再分享

Reference#

https://github.com/dotnetcore/AspectCore-Framework https://github.com/dotnetcore/AspectCore-Framework/blob/master/src/AspectCore.Core/Utils/ProxyGeneratorUtils.cs https://github.com/castleproject/Core https://github.com/castleproject/Core/blob/master/src/Castle.Core/DynamicProxy/ModuleScope.cs https://github.com/dotnet/runtime/blob/master/src/libraries/System.Reflection.DispatchProxy/src/System/Reflection/DispatchProxyGenerator.cs https://github.com/WeihanLi/SamplesInPractice/blob/master/AopSample/Program.cs

作者: WeihanLi

出處:

https://www.cnblogs.com/weihanli/p/12713908.html

繼續閱讀