.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

相关文章
|
11月前
|
设计模式 Java 开发者
如何快速上手【Spring AOP】?从动态代理到源码剖析(下篇)
Spring AOP的实现本质上依赖于代理模式这一经典设计模式。代理模式通过引入代理对象作为目标对象的中间层,实现了对目标对象访问的控制与增强,其核心价值在于解耦核心业务逻辑与横切关注点。在框架设计中,这种模式广泛用于实现功能扩展(如远程调用、延迟加载)、行为拦截(如权限校验、异常处理)等场景,为系统提供了更高的灵活性和可维护性。
1429 0
|
XML 安全 Java
Spring AOP—深入动态代理 万字详解(通俗易懂)
Spring 第四节 AOP——动态代理 万字详解!
638 24
|
C# Android开发 iOS开发
2025年全面的.NET跨平台应用框架推荐
2025年全面的.NET跨平台应用框架推荐
844 23
|
消息中间件 开发框架 监控
NET任务调度框架Hangfire使用指南
Hangfire 是一个用于 .NET 应用程序的开源任务调度框架,支持长时间运行任务、定时任务等。通过简单的安装配置,即可将任务从主线程分离,提升应用性能。支持多种数据库,提供丰富的任务类型如立即执行、延迟执行和周期性任务,并有可视化管理界面 Hangfire Dashboard。还支持安全性配置及扩展插件,如 Hangfire.HttpJob,适合各种复杂场景下的任务调度需求。
1728 1
NET任务调度框架Hangfire使用指南
|
监控 前端开发 API
一款基于 .NET MVC 框架开发、功能全面的MES系统
一款基于 .NET MVC 框架开发、功能全面的MES系统
774 5
|
Java 开发者 Spring
Spring AOP深度解析:探秘动态代理与增强逻辑
Spring框架中的AOP(Aspect-Oriented Programming,面向切面编程)功能为开发者提供了一种强大的工具,用以将横切关注点(如日志、事务管理等)与业务逻辑分离。本文将深入探讨Spring AOP的底层原理,包括动态代理机制和增强逻辑的实现。
407 4
|
开发框架 安全 .NET
在数字化时代,.NET 技术凭借跨平台兼容性、丰富的开发工具和框架、高效的性能及强大的安全稳定性,成为软件开发的重要支柱
在数字化时代,.NET 技术凭借跨平台兼容性、丰富的开发工具和框架、高效的性能及强大的安全稳定性,成为软件开发的重要支柱。它不仅加速了应用开发进程,提升了开发质量和可靠性,还促进了创新和业务发展,培养了专业人才和技术社区,为软件开发和数字化转型做出了重要贡献。
432 5
|
安全 Java 开发者
AOP中的JDK动态代理与CGLIB动态代理:深度解析与实战模拟
【11月更文挑战第21天】面向切面编程(AOP,Aspect-Oriented Programming)是一种编程范式,它通过将横切关注点(cross-cutting concerns)与业务逻辑分离,以提高代码的可维护性和可重用性。在Java开发中,AOP的实现离不开动态代理技术,其中JDK动态代理和CGLIB动态代理是两种常用的方式。本文将从背景、历史、功能点、业务场景、底层逻辑等多个维度,深度解析这两种代理方式的区别,并通过Java示例进行模拟和比较。
1110 5
|
传感器 人工智能 供应链
.NET开发技术在数字化时代的创新作用,从高效的开发环境、强大的性能表现、丰富的库和框架资源等方面揭示了其关键优势。
本文深入探讨了.NET开发技术在数字化时代的创新作用,从高效的开发环境、强大的性能表现、丰富的库和框架资源等方面揭示了其关键优势。通过企业级应用、Web应用及移动应用的创新案例,展示了.NET在各领域的广泛应用和巨大潜力。展望未来,.NET将与新兴技术深度融合,拓展跨平台开发,推动云原生应用发展,持续创新。
258 4
|
开发框架 .NET C#
.NET 技术凭借高效开发环境、强大框架支持及跨平台特性,在软件开发中占据重要地位
.NET 技术凭借高效开发环境、强大框架支持及跨平台特性,在软件开发中占据重要地位。从企业应用到电子商务,再到移动开发,.NET 均展现出卓越性能,助力开发者提升效率与项目质量,推动行业持续发展。
488 4