.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 来创建代理

Copy
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));

}
使用示例:

Copy
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

相关文章
|
24天前
|
设计模式 开发框架 JavaScript
基于.NET8 + Vue/UniApp前后端分离的快速开发框架,开箱即用!
基于.NET8 + Vue/UniApp前后端分离的快速开发框架,开箱即用!
|
2月前
|
XML JSON API
ServiceStack:不仅仅是一个高性能Web API和微服务框架,更是一站式解决方案——深入解析其多协议支持及简便开发流程,带您体验前所未有的.NET开发效率革命
【10月更文挑战第9天】ServiceStack 是一个高性能的 Web API 和微服务框架,支持 JSON、XML、CSV 等多种数据格式。它简化了 .NET 应用的开发流程,提供了直观的 RESTful 服务构建方式。ServiceStack 支持高并发请求和复杂业务逻辑,安装简单,通过 NuGet 包管理器即可快速集成。示例代码展示了如何创建一个返回当前日期的简单服务,包括定义请求和响应 DTO、实现服务逻辑、配置路由和宿主。ServiceStack 还支持 WebSocket、SignalR 等实时通信协议,具备自动验证、自动过滤器等丰富功能,适合快速搭建高性能、可扩展的服务端应用。
138 3
|
24天前
|
消息中间件 监控 数据可视化
基于.NET开源、功能强大且灵活的工作流引擎框架
基于.NET开源、功能强大且灵活的工作流引擎框架
|
24天前
|
开发框架 网络协议 .NET
C#/.NET/.NET Core优秀项目和框架2024年10月简报
C#/.NET/.NET Core优秀项目和框架2024年10月简报
|
24天前
|
网络协议 Unix Linux
精选2款C#/.NET开源且功能强大的网络通信框架
精选2款C#/.NET开源且功能强大的网络通信框架
|
24天前
|
开发框架 JavaScript 前端开发
2024年全面且功能强大的.NET快速开发框架推荐,效率提升利器!
2024年全面且功能强大的.NET快速开发框架推荐,效率提升利器!
|
24天前
|
网络协议 网络安全 Apache
一个整合性、功能丰富的.NET网络通信框架
一个整合性、功能丰富的.NET网络通信框架
|
2月前
|
开发框架 前端开发 API
C#/.NET/.NET Core优秀项目和框架2024年9月简报
C#/.NET/.NET Core优秀项目和框架2024年9月简报
|
2月前
|
Linux C# Android开发
.NET开源跨平台桌面和移动应用的统一框架 - Eto.Forms
.NET开源跨平台桌面和移动应用的统一框架 - Eto.Forms
145 1
|
2月前
|
开发框架 JavaScript 前端开发
一个适用于 ASP.NET Core 的轻量级插件框架
一个适用于 ASP.NET Core 的轻量级插件框架