上一篇《更加简练的编程体验》提供了最新版本的Dora.Interception代码的AOP编程体验,接下来我们会这AOP框架的编程模式进行详细介绍,本篇文章着重关注的是拦截器的定义。采用“基于约定”的Interceptor定义方式是Dora.Interception区别于其他AOP框架的一个显著特征,要了解拦截器的编程约定,就得先来了解一下Dora.Interception中针对方法调用的拦截是如何实现的。

一、针对实例的拦截

总地来说,Dora.Interception针对方法调用的拦截机制分为两种类型,我将它称为“针对实例的拦截”和“针对类型”的拦截。针对实例的拦截应用于针对接口的方法调用,其原理如下所示:类型Foobar实现了接口IFoobar,如果需要拦截以接口的方式调用Foobar对象的某个方法,我们可以动态生成另一个用来封装Foobar对象的FoobarProxy类型,FoobarProxy同样实现IFoobar接口,我们在实现的方法中实现对Interceptor链的调用。我们最终将原始提供的Foobar对象封装成FoobarProxy对象,那么针对Foobar的方法调用将转换成针对FoobarProxy对象的调用,拦截得以实现。

二、针对类型的拦截

如果Foobar并未实现任何接口,或者针对它的调用并非以接口的方式进行,那么我们只能采用“针对类型的拦截”,其原理如下:我们动态创建Foobar的派生类型FoobarProxy,并重写其需要被拦截的虚方法来实现对Interceptor链的调用。我们最终创建FoobarProxy对象来替换掉原始的Foobar对象,那么针对Foobar的方法调用将转换成针对FoobarProxy对象的调用,拦截得以实现。

由于这种拦截方式会直接创建代理对象,无法实现针对目标对象的封装,当我们进行DI服务注册的时候,只能指定注册服务的实现类型,不能指定一个现有的Singleton实例或者提供一个创建实例的Factory。

三、从两个Delegate说起

要理解Dora.Interception的设计,先得从如下这两个特殊的Delegate类型(InterceptDelegateInterceptorDelegate)说起。InterceptDelegate代表针对方法的拦截操作,作为输入参数的InvocationContext提供了当前方法调用的所有上下文信息,返回类型被设置为Task意味着Dora.Interception提供了针对基于Task的异步编程的支持。

public delegate Task InterceptDelegate(InvocationContext context);
public delegate InterceptDelegate InterceptorDelegate(InterceptDelegate next);
public abstract class InvocationContext
{
public abstract object[] Arguments { get; }
public abstract MethodBase Method { get; }
public InterceptDelegate Next { get; }
public abstract object Proxy { get; }
public abstract object ReturnValue { get; set; }
public abstract object Target { get; }
public MethodBase TargetMethod { get; }
public abstract IDictionary<string, object> ExtendedProperties { get; } public Task ProceedAsync();
}

InterceptDelegate表示的是“拦截操作”,即表示作用于InvocationContext上下文上的一个Task,但它并不能表示一个拦截器对象。原因很简单,因为注册到同一个方法上的多个拦截器对象会构成一个链条,最终决定是否调用后一个拦截器或者目标方法(对于链条尾部的Interceptor)是由当前拦截器决定的,所以如果将Interceptor也表示成委托对象,它的输入应该是一个InterceptDelegate对象,表示针对后一个拦截器或者目标方法的调用,它返回的同样也是一个InterceptDelegate对象,表示将自身纳入拦截器链之后,新的拦截器链条(包括调用目标方法)所执行的操作。

所以一个Interceptor在Dora.Interception中应该表示成一个Func<InterceptDelegate, InterceptDelegate>对象,这与ASP.NET Core的中间件管道其实是一回事。简单起见,我们为它专门定义了一个委托类型InterceptorDelegate。

四、将一个对象转换成Interceptor

虽然Dora.Interception总是将Interceptor对象表示成上面介绍的InterceptorDelegate类型的委托,但是为了更好的编程体验,我们可以选择采用POCO类型的方法来定义Interceptor。为了提供更好的灵活性,能够在方法中动态注入任意依赖服务,我们并不打算为这样的Interceptor类型定义一个接口。接口是一个契约,同时也是一个限制。如果类型实现某个接口,意味着必需按照规定的声明实现其方法,针对方法的服务注入将无法实现,所以Dora.Interception采用“基于约定”的方式来定义Interceptor类型。具体的约定如下

  • Interceptor只需要定义一个普通的实例类型即可。
  • Interceptor类型必须具有一个公共构造函数,它可以包含任意的参数,并支持构造器注入
  • 拦截功能实现在约定的InvokeAsync的方法中,这是一个返回类型为Task的异步方法,它的第一个参数类型为InvocationContext
  • 除了表示当前执行上下文的参数之外,
    任何可以注入的服务于对象都可以定义成InvokeAsync方法的参数。
  • 当前Interceptor针对后续的Interceptor或者目标方法的调用通过调用InvocationContext的ProceedAsync方法来实现。

如下所示的就是一个典型的Interceptor,它提供了针对构造函数和方法的注入。

public class FoobarInterceptor
{
public IFoo Foo { get; }
public string Baz { get; }
public FoobarInterceptor(IFoo foo, string baz)
{
Foo = foo;
Baz = baz;
} public async Task InvokeAsync(InvocationContext context, IBar bar)
{
await Foo.DoSomethingAsync();
await bar.DoSomethingAsync();
await context.ProceedAsync();
}
}

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

Dora.Interception,为.NET Core度身打造的AOP框架 [2]:以约定的方式定义拦截器的更多相关文章

  1. Dora.Interception, 为.NET Core度身打造的AOP框架:不一样的Interceptor定义方式

    相较于社区其他主流的AOP框架,Dora.Interception在Interceptor提供了完全不同的编程方式.我们并没有为Interceptor定义一个接口,正是因为不需要实现一个预定义的接口, ...

  2. Dora.Interception,为.NET Core度身打造的AOP框架:全新的版本

    Dora.Interception 1.0(Github地址:可以访问GitHub地址:https://github.com/jiangjinnan/Dora)推出有一段时间了,最近花了点时间将它升级 ...

  3. Dora.Interception, 为.NET Core度身打造的AOP框架[4]:演示几个典型应用

    为了帮助大家更深刻地认识Dora.Interception,并更好地将它应用到你的项目中,我们通过如下几个简单的实例来演示几个常见的AOP应用在Dora.Interception下的实现.对于下面演示 ...

  4. Dora.Interception, 为.NET Core度身打造的AOP框架[3]:Interceptor的注册

    在<不一样的Interceptor>中我们着重介绍了Dora.Interception中最为核心的对象Interceptor,以及定义Interceptor类型的一些约定.由于Interc ...

  5. Dora.Interception, 一个为.NET Core度身打造的AOP框架:不一样的Interceptor定义方式

    相较于社区其他主流的AOP框架,Dora.Interception在Interceptor提供了完全不同的编程方式.我们并没有为Interceptor定义一个接口,正是因为不需要实现一个预定义的接口, ...

  6. Dora.Interception, 一个为.NET Core度身打造的AOP框架[3]:Interceptor的注册

    在<不一样的Interceptor>中我们着重介绍了Dora.Interception中最为核心的对象Interceptor,以及定义Interceptor类型的一些约定.由于Interc ...

  7. Dora.Interception,为.NET Core度身打造的AOP框架 [3]:多样化拦截器应用方式

    在<以约定的方式定义拦截器>中,我们通过对拦截器的介绍了Dora.Interception的两种拦截机制,即针对接口的“实例拦截”针对虚方法的“类型拦截”.我们介绍了拦截器的本质以及基于约 ...

  8. Dora.Interception,为.NET Core度身打造的AOP框架 [1]:更加简练的编程体验

    很久之前开发了一个名为Dora.Interception的开源AOP框架(github地址:https://github.com/jiangjinnan/Dora,如果你觉得这个这框架还有那么一点价值 ...

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

    这里所谓的与第三方AOP框架的整合不是说改变Dora.Interception现有的编程,而是恰好相反,即在不改变现有编程模式下采用第三方AOP框架或者自行实现的拦截机制.虽然我们默认提供基于IL E ...

  10. Dora.Interception,为.NET Core度身打造的AOP框架 [4]:与依赖注入框架的无缝集成

    Dora.Interception最初的定位就是专门针对.NET Core的AOP框架,所以在整个迭代过程中我大部分是在做减法.对于.NET Core程序开发来说,依赖注入已经成为无处不在并且“深入骨 ...

随机推荐

  1. 使用Node.js+Hexo+Github搭建个人博客

    一.为什么要花时间去搭建个人博客? 首先说说为什么我想要尝试着去搭建属于自己的Blog,古人云:“好记性不如烂笔头”.一开始我把笔记做在本子上.电脑上,发现要用的时候特别地不方便,而且越记越多.越多越 ...

  2. C语言中return 0和return 1和return -1

    转载声明:本文系转载文章 原文作者:十一月zz 原文地址:https://blog.csdn.net/baidu_35679960/article/details/77542787 1.返回值int  ...

  3. JQuery插件:ScrollTo平滑滚动到页面指定位置

    1.准备jQuery库和scrollTo.js插件. <script type="text/javascript" src="js/jquery.js"& ...

  4. python之地基(二)

    上一个阶段呢,我们已经学习了python的数据的类型.今天呢,我们来学习各种各样的运算符. 一.基本运算符 a = 10    b = 20 运算符号 描述 示例 + 加——两个对象相加 a+b 输出 ...

  5. 第一个 Python 程序

    ## 目标 * 第一个 `HelloPython` 程序* `Python 2.x` 与 `3​​.x` 版本简介* 执行 `Python` 程序的三种方式 * 解释器 —— `python` / ` ...

  6. cocos creator 动画编辑器以及骨骼动画的使用

    一.普通动画的设置 1.添加动画组件 a.添加空节点=>添加动画组件 b.新建Clip文件=>打开编辑模式添加动画编辑(并且把添加的clip文件拖动到右边面板的Default Clip 与 ...

  7. Spring Cloud 快速入门

     Spring Cloud快速入门 代码地址: https://gitee.com/gloryxu/spring-cloud-test EureKa:服务注册中心 添加依赖 <dependenc ...

  8. Win7共享文件夹简单?这个共享问题可以难倒90%的人

    信息化社会,没有哪个公司不用电脑办公了.一个办公室里面的同事相互之间利用系统的共享功能,共享一些文件和软件已经是司空见惯的了,这个不需要多么复杂的操作.我们使用最多的windows7操作系统就能很方便 ...

  9. 小程序-组件component和模版template的选择和使用

    小程序提供了组件component和模版template那什么时候 选择哪一个使用呢?我总结了一下 template主要是模版,对于重复的展示型模块进行展示,其中调用的方法或者数据data都是需要引用 ...

  10. Linux学习之文件系统权限及表示

    三类人 用户主(user:u):文件的所有者 同组人(group:g):与文件主同组的用户 其他人(other:o):除用户主和同组人外的其他所有人 三种权限 读权限(r):指用户对文件或目录的读许可 ...