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

  • 提供了原生的动态代理生成底层框架Dora.DynamicProxy:之前依赖第三方框架Castle实现最底层的代理生成,但是它不支持基于Task的并行编程(也就是说通过它编写的Interceptor无法实现异步执行),所以我采用IL Emit的方式自行实现了这部分的功能,这些底层的功能实现在Dora.DynamicProxy中。
  • 提供了如下两种形式的拦截方案:
    • 基于实例封装:如果消费的类型是一个接口,那么提供的类型为动态生成的代理类,该代理类封装了目标对象。对于每一个动态生成的接口实现成员来说,它会负责执行应用的Interceptor。如果需要调用目标方法,被封装的目标对象的对应方法会被调用。这种拦截方案要求目标类型实现一个接口,接口中定义的所有方法和属性都是可以被拦截的。
    • 基于类型继承:如果目标类型是一个非Sealed类型,一个继承与它的代理类型会被动态生成。如果Interceptor被应用到目标类型的某个虚方法或者属性上,该成员会在生成的代理类中被重写,进而使Interceptor得以执行。这种拦截机制适合非Sealed类型,只有虚方法/属性能够被拦截。
  • 提供了针对属性的拦截支持:之前的版本支持针对方法的拦截,最新版本中提供了针对属性的拦截支持。我们可以选择将Interceptor应用到某个类型的属性上,也可以单独应用到该属性的Get或者Set方法上。

一、对基于Task的并行编程的支持

由于Dora.Interception将Dora.DynamicProxy作为默认的动态代理类型生成框架,所以不在依赖任何第三发框架,因此在编程会变得更加简单,现在我们来做一个简单的演示。在安装了最新版本的NuGet包Dora.Interception之后,我们可以按照 “约定” 的方式来定义如下这么一个简单的Interceptor类型。为了验证针对Task并行编程的支持,我们特意在拦截方法InvokeAsync中Delay了一秒钟。

public class FoobarInterceptor
{
private InterceptDelegate _next; public FoobarInterceptor(InterceptDelegate next)
{
_next = next;
}
public async Task InvokeAsync(InvocationContext context)
{
Console.WriteLine("Interception task starts.");
await Task.Delay();
Console.WriteLine("Interception task completes.");
await _next(context);
}
}

我将Interceptor和Interceptor的注册特意区分开来,Interceptor的注册默认采用特性标注的形式来实现,为此我们为上面定义的FoobarInterceptor创建一个对应的特性类型FoobarAttribute。如下面的代码片段所示,FoobarAttribute派生于InterceptorAttribute,FoobarInterceptor在重写的Use方法中被构建,在构建过程中可以指定该Interceptor在整个Interceptor Chain的位置(Order)。

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Property)]
public class FoobarAttribute : InterceptorAttribute
{
public override void Use(IInterceptorChainBuilder builder)
{
builder.Use<FoobarInterceptor>(this.Order);
}
}

接下来我们定义了简单的类型Demo来使用FoobarInterceptor,Demo实现了接口IDemo,FoobarAttribute标注在需要被拦截的方法InvokeAsync上。

public interface IDemo
{
Task InvokeAsync();
} public class Demo : IDemo
{
[Foobar]
public Task InvokeAsync()
{
Console.WriteLine("Target method is invoked.");
return Task.CompletedTask;
}
}

由于Dora.Interception实现了与.NET Core的Dependency Injection的无缝集成,所以我们只需要采用我们熟悉的方式来提供服务实例就可以了。如下面的代码片段所示,我们将IDemo和Demo之间的映射关系注册到创建的ServiceCollection上之后,并没有调用BuildeServiceProvider方法,而是调用BuildInterceptableServiceProvider来创建提供服务的ServiceProvider。

class Program
{
static void Main(string[] args)
{
var demo = new ServiceCollection()
.AddSingleton<IDemo, Demo>()
.BuildeInterceptableServiceProvider()
.GetRequiredService<IDemo>();
demo.InvokeAsync();
Console.WriteLine("Continue...");
Console.Read();
}
}

如下所示的是这段代码的执行结果,我们可以看到应用的FoobarInterceptor被正常执行,而且它完全是以异步的方式执行的。

二、基于虚方法的拦截

如果Demo没有实现任何的接口,并且它不是一个Sealed类型,它的虚方法和属性也是可以被拦截的。比如我们将Demo做了如下的改动。

public class Demo
{
[Foobar]
public virtual Task InvokeAsync()
{
Console.WriteLine("Target method is invoked.");
return Task.CompletedTask;
}
}

所有Demo没有了接口实现,所以我们需要对服务注册代码做相应的修改。执行修后的代码,我们依然会得到相同的输出。

class Program
{
static void Main(string[] args)
{
var demo = new ServiceCollection()
.AddSingleton<Demo, Demo>()
.BuildeInterceptableServiceProvider()
.GetRequiredService<Demo>();
demo.InvokeAsync();
Console.WriteLine("Continue...");
Console.Read();
}
}

三、属性也可被拦截

对于上一版本来说,被拦截的成员仅限于普通的方法,最新的版本增加对属性的支持。如果一个Interceptor被直接应用到某个属性上,它实际上会被同时应用到该属性的Get和Set方法上。比如我们在Demo类型上添加一个Value属性,并在上面标准FoobarAttribute。

public class Demo
{
[Foobar]
public virtual object Value { get; set; }
}

接下来我们按照如下的方式获取一个Demo对象,并调用其Value属性的Set和Get方法。

class Program
{
static void Main(string[] args)
{
var demo = new ServiceCollection()
.AddSingleton<Demo, Demo>()
.BuildInterceptableServiceProvider()
.GetRequiredService<Demo>();
Console.WriteLine("Set...");
demo.Value = new object();
Console.WriteLine("Get...");
var value = demo.Value;
Console.Read();
}
}

从如下的输出结果可以看出,我们注册到Value属性上的FoobarInterceptor在Get和Set方法被调用的时候都执行了一遍。

如果我们只需要在某个属性的Get或者Set方法上应用某个Interceptor,我们也可以作针对性的标注。在如下的代码片段中,我们将FoobarAttrbute标准到Get方法上。

public class Demo
{
public virtual object Value { [Foobar] get; set; }
}

再次执行程序,我们会发现FoobarInterceptor仅仅在调用Value属性的Get方法时被执行了一次。

Dora.Interception, 为.NET Core度身打造的AOP框架 [1]:全新的版本
Dora.Interception, 为.NET Core度身打造的AOP框架 [2]:不一样的Interceptor定义方式
Dora.Interception, 为.NET Core度身打造的AOP框架 [3]:Interceptor的注册
Dora.Interception, 为.NET Core度身打造的AOP框架 [4]:演示几个典型应用

Dora.Interception,为.NET Core度身打造的AOP框架:全新的版本的更多相关文章

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

随机推荐

  1. linux定时器crontab

    linux定时器crontab用法: 1.基本格式 : * * * * * command 分 时 日 月 周 命令 第1列表示分钟1-59 每分钟用*或者 */1表示 第2列表示小时1-23(0表示 ...

  2. spring cloud sidecar

    用spring cloud sidecar的整合异构语言,以前做过没有做笔记,现在再做由于各种坑又浪费了一天,这里记一下 首先是官网:http://cloud.spring.io/spring-clo ...

  3. go编程之常见工具函数

    1.时间格式化 基于模式的布局进行时间格式化和解析 package main import "fmt" import "time" func main() { ...

  4. softmax分类算法原理(用python实现)

    逻辑回归神经网络实现手写数字识别 如果更习惯看Jupyter的形式,请戳Gitthub_逻辑回归softmax神经网络实现手写数字识别.ipynb 1 - 导入模块 import numpy as n ...

  5. css弹性盒子新旧兼容

    前言:本篇随笔是对弹性盒子有了解的人来写的这篇文章,具体属性产生的效果这里不做说明,基础的东西去查文档.这里只是总结. 时至今日,css3的flex弹性盒子在移动端基本上都是支持的,但不排除有些些低版 ...

  6. cleanMyMac

    想看外国网站可以找我,facebook.youtube.XX大片等,只要8元钱,无限制用到服务器关闭.看大片流畅不成问题 需要cleanMyMac的请加微信只要10或直接拍 http://a.p6ff ...

  7. 类的更新----MVC设计模式

    <?php class stdObject { public function __construct(array $arguments = array()) { if (!empty($arg ...

  8. Android -- NestedScrolling滑动机制

    1,如今NestedScrolling运用到很多地方了,要想好看一点的滑动变换,基本上就是使用这个来完成的,让我们来简单的了解一下. 2,NestedScrolling机制能够让父View和子View ...

  9. HTML学习 框架

    iframe 在原来的页面嵌入其他页面 <iframe src="其他页面地址" width="宽" height="高" frame ...

  10. ubuntu16.04编译安装php7.2

    1,下载解压 tar xf php-7.2.0.tar.gz cd php-7.2.0/ 2,安装必要的库 sudo apt-get install libxml2-devsudo apt-get i ...