Dora.Interception,为.NET Core度身打造的AOP框架 [5]:轻松地实现与其他AOP框架的整合

这里所谓的与第三方AOP框架的整合不是说改变Dora.Interception现有的编程,而是恰好相反,即在不改变现有编程模式下采用第三方AOP框架或者自行实现的拦截机制。虽然我们默认提供基于IL Emit实现方式,并且对IL指令进行了深度的优化,但是如果我们真的具有更好的选择,我们可以通过简单的扩展完成对底层拦截机制改变。

一、IInterceptingProxyFactory

对于Dora.Interception来说,方法调用之所有能够被拦截的根源在于我们改变了服务实例的提供方式,原来的对象被替换成了可被拦截的代理对象。针对代理对象的提供体现在如下这个IInterceptingProxyFactory接口上。如果提供类型体现为一个接口,Wrap方法会被调用来创建一个封装目标对象的代理(如果不需要被拦截,则直接返回目标对象);如果提供类型体现为一个类型,Create方法则被用来实现对代理对象的创建,如果不需要被拦截,方法提供的后面两个参数会被用来提供目标对象。

public interface IInterceptingProxyFactory
{
    IServiceProvider ServiceProvider { get; }

    object Wrap(Type typeToIntercept, object target);
    object Create(Type typeToIntercept, IServiceProvider serviceProvider, Func<object> targetAccessor = null);
}

二、InterceptingProxyFactoryBase

Dora.Interception提供了如下一个实现了IInterceptingProxyFactory接口的基类InterceptingProxyFactoryBase。后者帮助我们实现针对拦截器的解析,解析后的拦截器体现为一个InterceptorDecoration对象。作为它的派生类型只需要实现两个受保护的虚方法Wrap和Create根据解析出来的拦截器实现可被拦截的代理对象的创建。

public abstract class InterceptingProxyFactoryBase : IInterceptingProxyFactory
{
    public IInterceptorResolver InterceptorResolver { get; }
    public IServiceProvider ServiceProvider { get; }
    public InterceptingProxyFactoryBase(IInterceptorResolver interceptorResolver, IServiceProvider serviceProvider);    
    
    public object Create(Type typeToIntercept, IServiceProvider serviceProvider, Func<object> targetAccessor = null);
    public object Wrap(Type typeToIntercept, object target);

    protected virtual bool CanIntercept(Type typeToIntercept);
    protected abstract object Wrap(Type typeToIntercept, object target, InterceptorDecoration interceptors);
    protected abstract object Create(Type typeToIntercept, IServiceProvider serviceProvider, InterceptorDecoration interceptors);
}

如果所示的是InterceptorDecoration, 我们可以得到应用到目标类型中所有方法(包括属性的Get和Set方法)上的拦截器(实际上所有拦截器按照指定顺序构建而成的拦截器管道,最终体现为一个类型为InterceptorDelegate 的委托对象)。

public sealed class InterceptorDecoration
{
    public InterceptorDelegate GetInterceptor(MethodInfo methodInfo);
    public MethodInfo GetTargetMethod(MethodInfo methodInfo);
    public bool IsInterceptable(MethodInfo methodInfo);

    public IReadOnlyDictionary<int, InterceptorDelegate> Interceptors { get; }
    public bool IsEmpty { get; }
    public IReadOnlyDictionary<MethodInfo, MethodBasedInterceptorDecoration> MethodBasedInterceptors { get; }
    public IReadOnlyDictionary<PropertyInfo, PropertyBasedInterceptorDecoration> PropertyBasedInterceptors { get; }
}

public class MethodBasedInterceptorDecoration
{
    public InterceptorDelegate Interceptor { get; }
    public MethodInfo Method { get; }
}

public class PropertyBasedInterceptorDecoration
{   
    public PropertyInfo Property { get; }
    public MethodBasedInterceptorDecoration GetMethodBasedInterceptor { get; }
    public MethodBasedInterceptorDecoration SetMethodBasedInterceptor { get; }
}

自定义的IInterceptingProxyFactory实现只需要按照普通的服进行注册即可。

三、针对Castle的集成

由于Castle原生的框架并没有提供针对Task的支持,所以我们利用另一个名为Castle.Core.AsyncInterceptor将Castle的拦截实现整合到Dora.Interception。具体的实现体现在如下这个DynamicProxyFactory中。该类型对应的NuGet包为“Dora.Interception.Castle”。

public class DynamicProxyFactory : InterceptingProxyFactoryBase
{   
    public DynamicProxyFactory(IInterceptorResolver interceptorResolver, IServiceProvider serviceProvider);
    protected override object Create(Type typeToIntercept, IServiceProvider serviceProvider, InterceptorDecoration interceptors);
    protected override object Wrap(Type typeToIntercept, object target, InterceptorDecoration interceptors);
}

如果需要采用基于Caslte的拦截实现机制,我们只需要做如下的设置即可。

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {        
        services
            ...
            AddInterception(builder=>builder.SetCastleDynamicProxy());
    }
    ...
}

或者

public class Startup
{
    public IServiceProvider ConfigureServices(IServiceCollection services)
    {        
        return services
            ...
            .BuildInterceptableServiceProvider(builder=>builder.SetCastleDynamicProxy());
    }
    ...
}

[1]:更加简练的编程体验 [2]:基于约定的拦截器定义方式 [3]:多样性的拦截器应用方式 [4]:与依赖注入框架的深度整合 [5]:对拦截机制的灵活定制

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏分布式系统进阶

Influxdb 数据写入流程

因此对写入请求的处理就在函数 func (h *Handler) serveWrite(w http.ResponseWriter, r *http.Reque...

1663
来自专栏游戏杂谈

fabrication的拦截器Interceptors简介

Interceptors(拦截器),主要目的是为了改变PureMVC的消息通知在到达Commands和Mediators的正常执行顺序。 在拦截器里可以:

852
来自专栏大内老A

.NET Core的日志[5]:利用TraceSource写日志

从微软推出第一个版本的.NET Framework的时候,就在“System.Diagnostics”命名空间中提供了Debug和Trace两个类帮助我们完成针...

2456
来自专栏逆向技术

x64内核HOOK技术之拦截进程.拦截线程.拦截模块

            x64内核HOOK技术之拦截进程.拦截线程.拦截模块 一丶为什么讲解HOOK技术. 在32系统下, 例如我们要HOOK SSDT表,那么...

4747
来自专栏大内老A

框架升级后某个类型所在程序集发生转移,应用还能正常运行吗?

所谓类型转移(Type Forwarding)就是将定义在某个程序集中的类型转移到另一个程序集中。我们先通过一个简单的实例让读者朋友们对类型转移有一个感官上的认...

1856
来自专栏LanceToBigData

Hadoop(九)Hadoop IO之Compression和Codecs

前言   前面一篇介绍了Java怎么去查看数据块的相关信息和怎么去查看文件系统。我们只要知道怎么去查看就行了!接下来我分享的是Hadoop的I/O操作。   在...

2567
来自专栏osc同步分享

hibernate学习笔记

  Configuration configuration = new Configuration().configure();      ServiceReg...

28611
来自专栏程序员与猫

浅谈 EF CORE 迁移和实例化的几种方式

1043
来自专栏圣杰的专栏

Asp.net mvc 知多少(二)

本系列主要翻译自《ASP.NET MVC Interview Questions and Answers 》- By Shailendra Chauhan,想...

1988
来自专栏非典型技术宅

iOS核心机制之一:UITableView的Cell重用机制1 传统重用机制2. 注册机制的重用3. 注册cell的三种方式4. 调试小技巧之检测异常断点

1293

扫码关注云+社区