• ASP.NET WebAPI 14 仿写Filter管道


    WebAPI中有设计了几种管道(Channel),大概如下:HttpMessageHandler,ActionFilter管道,ExceptionFilter管道。在三种管道中HttpMessageHandler管道与ExceptionFilter管道是基于级别设计的,ActionFilter管道是基于方法级别设计的。对于ActionFilter管道,因为采用的是AOP的思想,所以按方法级别去设计。

    在看WebAPI源码过程中对ActionFilter管道中何用的表达示树与闭包等内容之前并没有下手写过,所以想仿写一个简单版的ActionFilter来练练手。

    在写demo的过程中,我将Action的返回值固定为ResponseMessage,在ActionFilter实现过程中并没有遵循WebAPI的具体规则,只是实现ActionFilter对Action执行前后的切入与多ActionFilter的注入。

    IActionFilter

     

    public interface IActionFilter
    
     { 
    
    Task<ResponseMessage> ExecuteActionFilterAsync(ActionContext actionContext, CancellationToken cancellationToken, Func<Task<ResponseMessage>> continuation); 
    
     }
    

     

    IActionFilter我是直接Copy源码里面的。IActionFilter接口,只定义了一个ExecuteActionFilterAsync方法。对于方法前两个参数好理解,至于最后一个类型为Func<Task<ResponseMessage>>的参数continuation,它是组成ActionFilter的关键。在WebAPI中将所有Action以及IActionFilter的ExecuteActionFilterAsync方法通过闭包的方式封装成Func<Task<ResponseMessage>>,再将每个Func<Task<ResponseMessage>逐级向ActionFilter中添加,以此来完成整个ActionFilter管道的构建。

    Action到Func<Task<ResponseMessage>>

    对于Action,因为我已经将返回值默认为ResponseMessage,所以我并没有对返回值做转换处理。因为Func<Task<ResponseMessage>>是一个无参的委托,所以在向Func<Task<ResponseMessage>>的转换分成两步:

    1. 定义类ActionInvoker(在demo中本身这个类并不是必须的,定义这个类主要是为是练习表达示树)
    2. 再针对ActionInvoker生成Func<Task<ResponseMessage>>
    Func<Task<ResponseMessage>> result = () => 
    
     { 
    
    return invoker.Invoke(context, cancellationToken); 
    
    };
    

     

     

    通过闭包生成ActionFilter管道

    之前已经提到将IActionFilter的ExecuteActionFilterAsync方法转换成Func<Task<ResponseMessage>>,并逐级添加到ActionFilter管道中,这个时候就必须要用到闭包了。

     

    ActionInvoker invoker = new ActionInvoker(context.Action); 
    
     
    
    Func<Task<ResponseMessage>> result = () => 
    
     { 
    
    return invoker.Invoke(context, cancellationToken); 
    
     }; 
    
     
    
    for (int i = 0; i <= filters.Count - 1; i++) 
    
     { 
    
    IActionFilter filter = filters[i]; 
    
     
    
    Func<Func<Task<ResponseMessage>>, IActionFilter, Func<Task<ResponseMessage>>> chainContinuation = 
    
     (continuation, innerFilter) => 
    
     { 
    
    return () => 
    
     { 
    
    return innerFilter.ExecuteActionFilterAsync(context, cancellationToken, continuation); 
    
     }; 
    
     }; 
    
     result = chainContinuation(result, filter); 
    
     }
    

    对于这个仿写的ActionFilter相对来说比较简单,所以以后有时候的话看能不能把Exception管道加进来,同时按照WebAPI的ActionFilter管道的规则去处理。

    源码

       

    Github: https://github.com/BarlowDu/WebAPI (FilterChannelDemo)

  • 相关阅读:
    系统程序员成长计划内存管理(一)
    系统程序员成长计划工程管理(二)
    嵌入式GUI ftk0.3发布
    嵌入式GUI FTK设计与实现目录
    嵌入式GUI FTK设计与实现分层视图
    sql 临时表的问题
    解惑XP系统IIS无法添加映射之诡异现象
    C#高质量缩略图
    C#图片处理之另存为压缩质量可自己控制的JPEG
    SQL注入
  • 原文地址:https://www.cnblogs.com/gangtianci/p/5003577.html
Copyright © 2020-2023  润新知