使用AspectCore动态代理

2017 年 11 月 23 日 DotNet

(点击上方蓝字,可快速关注我们)


来源:Lemon丶

cnblogs.com/liuhaoyang/p/aspectcore-getting-started.html


前言


最近越来越多的同学关注到AspectCore,并且提出不少中肯的建议,其中最多的提议是希望能够看到更多的关于AspectCore使用方式的文章和Demo。那么在这篇文章里,我们就来聊聊AspectCore核心之一的动态代理。


动态代理


在.NET平台中,静态织入和动态代理是实现AOP的两种方式。其中静态织入在编译时通过在MSBiuld执行自定义的Build Task来拦截编译过程,在生成的程序集里插入自己的IL。


而动态代理则是在运行时通过Emit技术生成动态程序集和动态代理类型从而对目标方法进行拦截。不管那种方式,都需要对MSIL有足够的理解,如果读者想要学习MSIL相关的技术,我在这里推荐《NET探秘MSIL权威指南》一书。


AspectCore使用了动态代理作为AOP的实现,而不使用理论上性能更优的静态织入实现,是由于个人觉得动态代理方式可以做到更好的IoC进行集成并且能够在切面中获取更多的运行时元数据信息,并且在经过不断优化后,AspectCore动态代理的性能已经不落后静态织入的实现方式。


如何使用


在之前的文章里,只是简单的介绍了AspectCore,导致了很多同学不知道如何在项目里使用AspectCore(^~^,求轻拍~)。下面就来讲一下如何在IoC环境和非IoC环境里使用AspectCore的AOP。


首先通过nuget获取AspectCore:


Install-Package AspectCore.Core


AspectCore中动态代理api在AspectCore.DynamicProxy命名空间中,所以我们需要先引入命名空间


using AspectCore.DynamicProxy;


在非IoC环境中,只使用AOP的话,AspectCore提供了ProxyGeneratorBuilder作为代理生成器创建的入口


ProxyGeneratorBuilder proxyGeneratorBuilder = new ProxyGeneratorBuilder();

IProxyGenerator proxyGenerator = proxyGeneratorBuilder.Build();


IProxyGenerator提供了CreateClassProxy方法创建class代理和CreateInterfaceProxy方法创建interface代理,创建的代理类被定义在命名为AspectCore.DynamicProxy.Generator的动态程序集中,并且代理类使用AspectCore.DynamicGenerated命名空间。


我们先来定义一个简单的拦截器,接着定义一个interface和它的简单实现,并创建interface的代理:


class Program

{

    static void Main(string[] args)

    {

        ProxyGeneratorBuilder proxyGeneratorBuilder = new ProxyGeneratorBuilder();

        IProxyGenerator proxyGenerator = proxyGeneratorBuilder.Build();

        SampleInterface sampleInterface = proxyGenerator.CreateInterfaceProxy<SampleInterface>();

        Console.WriteLine(sampleInterface);

        sampleInterface.Foo();

        Console.ReadKey();

    }

}


public class SampleInterceptor : AbstractInterceptorAttribute

{

    public override Task Invoke(AspectContext context, AspectDelegate next)

    {

        Console.WriteLine("call interceptor");

        return context.Invoke(next);

    }

}


public class SampleClass : SampleInterface

{

    public virtual void Foo() { }

}


[SampleInterceptor]

public interface SampleInterface

{

    void Foo();

}


将会输出:


AspectCore.DynamicGenerated.SampleInterface1

call interceptor


同时,IProxyGenerator提供了若干重载的扩展方法来创建已有类或接口实例的代理,可在ProxyGeneratorExtensions中找到并使用它们。


在IoC中使用AspectCore.DynamicProxy


AspectCore在设计之初就考虑AOP和IoC的集成使用,并提供AOP抽象接口以兼容不同IoC,目前已实现和AspectCore.DynamicProxy集成的IoC框架有:


  • AspectCore.Injector(AspectCore Framework的内置IoC)


  • Microsoft.Extensions.DependencyInjection(Asp.Net Core的内置DI框架)


  • Autofac


下面我们分别看一下在三个IoC中如何使用AspectCore.DynamicProxy。


AspectCore.Injector


AspectCore.Injector中内置了对AspectCore.DynamicProxy的支持,所以我们可以直接使用它:


IServiceContainer serviceContainer = new ServiceContainer();

serviceContainer.AddType<SampleInterface, SampleClass>();

IServiceResolver serviceResolver = serviceContainer.Build();

SampleInterface sampleInterface = serviceResolver.Resolve<SampleInterface>();

Console.WriteLine(sampleInterface);

sampleInterface.Foo();


输出:


AspectCore.DynamicGenerated.SampleClass

call interceptor


Microsoft.Extensions.DependencyInjection


AspectCore提供AspectCore.Extensions.DependencyInjection包集成Microsoft.Extensions.DependencyInjection和AspectCore.DynamicProxy。


通过nuget获取:


Install-Package AspectCore.Extensions.DependencyInjection


AspectCore提供了针对IServiceCollection的扩展方法AddDynamicProxy注册动态代理的接口和相关拦截器配置,并需要使用BuildAspectCoreServiceProvider创建被DynamicProxy接管的ServiceProvider:


IServiceCollection services = new ServiceCollection();

services.AddTransient<SampleInterface, SampleClass>();


services.AddDynamicProxy();

IServiceProvider serviceProvider = services.BuildAspectCoreServiceProvider();


SampleInterface sampleInterface = serviceProvider.GetService<SampleInterface>();

Console.WriteLine(sampleInterface);

sampleInterface.Foo();


输出:


AspectCore.DynamicGenerated.SampleClass

call interceptor


Autofac


AspectCore提供AspectCore.Extensions.Autofac包集成Autofac和AspectCore.DynamicProxy。


通过nuget获取:


Install-Package AspectCore.Extensions.Autofac


AspectCore提供了针对ContainerBuilder的扩展方法RegisterDynamicProxy注册动态代理的接口和相关拦截器配置


ContainerBuilder builder = new ContainerBuilder();

builder.RegisterType<SampleClass>().As<SampleInterface>();


builder.RegisterDynamicProxy();


var container = builder.Build();

SampleInterface sampleInterface = container.Resolve<SampleInterface>();

Console.WriteLine(sampleInterface);

sampleInterface.Foo();


输出:


AspectCore.DynamicGenerated.SampleClass

call interceptor


有问题反馈


如果您有任何问题,请提交 Issue 给我们。


Github : https://github.com/dotnetcore/AspectCore-Framework


看完本文有收获?请转发分享给更多人

关注「DotNet」,提升.Net技能 


淘口令复制以下红色内容,再打开手淘即可购买

范品社,使用¥极客T恤¥抢先预览(长按复制整段文案,打开手机淘宝即可进入活动内容)

登录查看更多
0

相关内容

IEEE国际需求工程会议是研究人员、实践者、教育工作者和学生展示和讨论需求工程学科最新创新、经验和关注点的首要国际论坛。这次会议将为学术界、政府和工业界提供一个广泛的项目,其中包括几位杰出的主旨演讲人和三天的会议,会议内容包括论文、专题讨论、海报和演示。官网链接:https://re20.org/
【KDD2020】自适应多通道图卷积神经网络
专知会员服务
119+阅读 · 2020年7月9日
【干货书】现代数据平台架构,636页pdf
专知会员服务
253+阅读 · 2020年6月15日
【实用书】流数据处理,Streaming Data,219页pdf
专知会员服务
76+阅读 · 2020年4月24日
《强化学习》简介小册,24页pdf
专知会员服务
271+阅读 · 2020年4月19日
【论文推荐】小样本视频合成,Few-shot Video-to-Video Synthesis
专知会员服务
23+阅读 · 2019年12月15日
MIT新书《强化学习与最优控制》
专知会员服务
275+阅读 · 2019年10月9日
用Now轻松部署无服务器Node应用程序
前端之巅
16+阅读 · 2019年6月19日
Kali Linux 渗透测试:密码攻击
计算机与网络安全
16+阅读 · 2019年5月13日
浅谈 Kubernetes 在生产环境中的架构
DevOps时代
11+阅读 · 2019年5月8日
基于Web页面验证码机制漏洞的检测
FreeBuf
7+阅读 · 2019年3月15日
百度开源项目OpenRASP快速上手指南
黑客技术与网络安全
5+阅读 · 2019年2月12日
免费云真机测试 | 让您的应用完美适配 Android Oreo
引力空间站
3+阅读 · 2018年2月2日
GAFT:一个使用 Python 实现的遗传算法框架
Python开发者
10+阅读 · 2017年8月1日
Attend More Times for Image Captioning
Arxiv
6+阅读 · 2018年12月8日
Arxiv
4+阅读 · 2018年5月4日
Arxiv
8+阅读 · 2018年5月1日
Arxiv
5+阅读 · 2018年1月23日
Arxiv
23+阅读 · 2017年3月9日
VIP会员
相关资讯
用Now轻松部署无服务器Node应用程序
前端之巅
16+阅读 · 2019年6月19日
Kali Linux 渗透测试:密码攻击
计算机与网络安全
16+阅读 · 2019年5月13日
浅谈 Kubernetes 在生产环境中的架构
DevOps时代
11+阅读 · 2019年5月8日
基于Web页面验证码机制漏洞的检测
FreeBuf
7+阅读 · 2019年3月15日
百度开源项目OpenRASP快速上手指南
黑客技术与网络安全
5+阅读 · 2019年2月12日
免费云真机测试 | 让您的应用完美适配 Android Oreo
引力空间站
3+阅读 · 2018年2月2日
GAFT:一个使用 Python 实现的遗传算法框架
Python开发者
10+阅读 · 2017年8月1日
Top
微信扫码咨询专知VIP会员