HTML5技术

Dora.Interception: 一个为.NET Core度身定制的AOP框架 - Artech(2)

字号+ 作者:H5之家 来源:H5之家 2017-05-02 11:00 我要评论( )

CacheInterceptor体现了一个典型的Interceptor的定义方式: Interceptor类型无需实现任何的接口,我们只需要定义一个普通的公共实例类型即可。 Interceptor类型必须具有一个公共构造函数,并且该构造函数的第一个参

CacheInterceptor体现了一个典型的Interceptor的定义方式:

  • Interceptor类型无需实现任何的接口,我们只需要定义一个普通的公共实例类型即可。
  • Interceptor类型必须具有一个公共构造函数,并且该构造函数的第一个参数的类型必须是InterceptDelegate,后者代表的委托对象会帮助我们调用后一个Interceptor或者目标方法(如果当前Interceptor已经是最后一个了)。
  • 上述这个构造函数可以包含任意的参数(比如CacheInterceptor构造函数中的cache和optionsAccessor)。这些参数可以直接利用.NET Core的Dependency Injection的方式进行注册,对于没有注册的参数需要在应用该Interceptor的时候显式提供。
  • 拦截功能实现在约定的InvokeAsync的方法中,这是一个返回类型为Task的异步方法,它的第一个参数类型为InvocationContext,代表当前方法调用的上下文。我们可以利用这个上下文对象得到Proxy对象和目标对象,代表当前调用方法的MethodInfo对象,以及传入的输入参数等。除此之外,我们也可以利用这个上下文直接设置方法的返回值或者输出参数。
  • 这个InvokeAsync方法可以包含任意后续参数,但是要求这些参数预先以Dependency Injection的形式进行注册。这也是我没有定义一个接口来表示Interceptor的原因,因为这样就不能将依赖的服务直接注入到InvokeAsync方法中了。
  • 当前Interceptor是否调用后续的Interceptor或者目标方法,取决于你是否调用构造函数传入的这个InterceptDelegate委托对象。
  • 由于依赖的服务对象(比如CacheInterceptor依赖IMemoryCache 和IOptions<MemoryCacheEntryOptions>对象)可以直接注入到InvokeAsync方法中,所以上述这个CacheInterceptor也可以定义成如下的形式

    1: public class CacheInterceptor 2: { 3:     private readonly InterceptDelegate _next; 4:     public CacheInterceptor(InterceptDelegate next) 5:     { 6:         _next = next; 7:     } 8:  9:     public async Task InvokeAsync(InvocationContext context, IMemoryCache cache, IOptions<MemoryCacheEntryOptions> optionsAccessor) 10:     { 11:         if (!context.Method.GetParameters().All(it => it.IsIn)) 12:         { 13:             await _next(context); 14:         } 15:  16:         var key = new Cachekey(context.Method, context.Arguments); 17:         if (cache.TryGetValue(key, out object value)) 18:         { 19:             context.ReturnValue = value; 20:         } 21:         else 22:         { 23:             await _next(context); 24:             _cache.Set(key, context.ReturnValue, optionsAccessor.Value); 25:         } 26:     } 27: }

    五、定义InterceptorAttribute

    我们采用Attribute的形式来将对应的Intercepor应用到某个类型或者方法上,每个具体的Interceptor类型都具有对应的Attribute。这样的Attribute直接继承基类InterceptorAttribute。如下这个CacheReturnValueAttribute就是上面这个CacheInterceptor对应的InterceptorAttribute。

    1: [AttributeUsage(AttributeTargets.Method)] 2: public class CacheReturnValueAttribute : InterceptorAttribute 3: { 4:     public override void Use(IInterceptorChainBuilder builder) 5:     { 6:         builder.Use<CacheInterceptor>(this.Order); 7:     } 8: }

    具体的InterceptorAttribute只需要重写Use方法将对应的Interceptor添加到Interceptor管道之中,这个功能可以直接调用作为参数的InterceptorChainBuilder对象的泛型方法Use<TInterceptor>来实现。对于这个泛型方法来说,泛型参数类型代表目标Interceptor的类型,而第一个参数表示注册的Interceptor在整个管道中的位置。如果创建目标Interceptor而调用的构造函数的参数尚未采用Dependency Injection的形式注册,我们需要在这个方法中提供。对于CacheInterceptor依赖的两个对象(IMemoryCache 和IOptions<MemoryCacheEntryOptions>)都可以采用Dependency Injection的形式注入,所以我们在调用Use<CacheInterceptor>方法是并不需要提供这个两个参数。

     

    1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

    相关文章
    • 如何在 ASP.NET Core 中发送邮件 - Savorboard

      如何在 ASP.NET Core 中发送邮件 - Savorboard

      2017-05-02 08:02

    • 【Vue 入门】使用 Vue2 开发一个展示项目列表的应用 - zhangjk

      【Vue 入门】使用 Vue2 开发一个展示项目列表的应用 - zhangjk

      2017-04-30 16:00

    • 十二个 ASP.NET Core 例子 - Savorboard

      十二个 ASP.NET Core 例子 - Savorboard

      2017-04-27 16:01

    • ASP.NET MVC5请求管道和生命周期 - 雪飞鸿

      ASP.NET MVC5请求管道和生命周期 - 雪飞鸿

      2017-04-24 08:04

    网友点评