.NET 下基于动态代理的 AOP 框架实现揭秘
.NET 下基于動態代理的 AOP 框架實現揭秘
Intro
之前基于 Roslyn 實現了一個簡單的條件解析引擎,想了解的可以看這篇文章?
基于 Roslyn 實現一個簡單的條件解析引擎
執行過程中會根據條件的不同會在運行時創建一個類,每一次創建都會生成一個新的程序集,我覺得這樣實現的話可能會導致加載的程序集越來越多,雖然目前我們的使用場景下不會有很多,而且相同的條件只會生成一次,還是覺得這樣不是特別好,此時想起來了一些 AOP 框架, Aspect.Core/ Castle/ DispatchProxy ,他們這些 AOP 框架會生成一些代碼類,好像也沒有生成很多額外的程序集,于是打算看看這些 AOP 框架的實現,看看它們是如何生成動態代理類的
動態代理實現原理
看了這三個 AOP 框架的實現代碼之后,實現原理基本都是一樣的
都是通過創建一個 DynamicAssembly 之后在這個 DynamicAssemly 中創建要動態生成代理類,通過 Emit 創建要生成動態代理類的方法/屬性等
來個小示例
多說不如來點代碼示例:
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<ITestService>(); 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
總結
以上是生活随笔為你收集整理的.NET 下基于动态代理的 AOP 框架实现揭秘的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: .Net微服务实战之技术架构分层篇
- 下一篇: Blazor WebAssembly 3