如何构造请求处理对象链(Pipeline)
在开发中,我们经常会遇到这样一个场景:传入一个对象,经过不同的节点对这个对象做不同的操作,比如ASP.NET Core 中的pipeline,IIS中的HTTPpipeline等。在这类问题中,往往我们允许用户可以自己定义自己的处理节点(Processor Node),能够实现这一目的的方式很多。本文中分享2种方式,欢迎大家交流。
责任链模式(Chain of Responsibility Pattern)
关于责任链模式的介绍园中已经有很多了,这里我就不再多余的来介绍了,直接上代码:
1. 创建抽象类
public abstract class ProcessorExecution
{
protected ProcessorExecution Next { get; private set; } protected ProcessorExecution(ProcessorExecution next = null)
{
Next = next;
} public virtual void Execute()
{
Next?.Execute();
} public ProcessorExecution SetNext(ProcessorExecution next)
{
Next = next;
return next;
}
}
2. 创建具体实现类
public class Node1ProcessorExecution : ProcessorExecution
{
public Node1ProcessorExecution(ProcessorExecution next = null) : base(next)
{
} public override void Execute()
{
Console.WriteLine("Node1 Processor");
base.Execute();
}
} public class Node2ProcessorExecution : ProcessorExecution
{
public Node2ProcessorExecution(ProcessorExecution next = null) : base(next)
{
} public override void Execute()
{
Console.WriteLine("Node2 Processor");
base.Execute();
}
} public class Node3ProcessorExecution : ProcessorExecution
{
public Node3ProcessorExecution(ProcessorExecution next = null) : base(next)
{
} public override void Execute()
{
Console.WriteLine("Node3 Processor");
base.Execute();
}
} public class TerminalProcessorExecute : ProcessorExecution
{
public TerminalProcessorExecute(ProcessorExecution next = null) : base(next)
{
} public override void Execute()
{
Console.WriteLine("Terminal Processor");
base.Execute();
}
}
3. 调用对象链
class Program
{
static void Main(string[] args)
{
var header = new Node1ProcessorExecution();
header.SetNext(new Node2ProcessorExecution())
.SetNext(new Node3ProcessorExecution())
.SetNext(new TerminalProcessorExecute());
header.Execute(); Console.Read();
}
}
委托链
有时候我们很不情愿地为一个Processor Node 去创建一个新类,因为那样显得类文件特别多,毕竟每一个类中只有一个或很少的方法需要重写。这里,我们可以尝试第二种方法 ---- 委托链,帮助我们减少类的创建。
在C#中,委托是一种特殊的类的方式存在,所以我们可以使用委托的方式实现。话不多说,直接上代码:
1. 创建一个委托
我们需要创建一个委托用来替代 ProcessorExecution中的Execute方法(Processor Node 处理的逻辑核心),.NET 4.5提供了async的编程方法,这里我使用Task来作为该委托的返回值:
public delegate Task ProcessorExecutionDelegate();
2. 创建一个Builder用于构造委托链
Builder中包括三个方法:
- ProcessorExecutionBuilder Add(Func<ProcessorExecutionDelegate, ProcessorExecutionDelegate> execution): 用来维护Current -> Next的关系。我们需要创建一个表示 Func<ProcessorExecutionDelegate, ProcessorExecutionDelegate> 的集合 _components。
- ProcessorExecutionBuilder Add(Func<Func<Task>, Task> middleware):用来表述NodeXProcessorExecution类(Func<Func<Task>, Task> middleware),内部调用Add(Func<ProcessorExecutionDelegate, ProcessorExecutionDelegate> execution)
- ProcessorExecutionDelegate Build():构造委托链,并返回Header节点
public class ProcessorExecutionBuilder
{
private readonly List<Func<ProcessorExecutionDelegate, ProcessorExecutionDelegate>> _components = new List<Func<ProcessorExecutionDelegate, ProcessorExecutionDelegate>>(); private ProcessorExecutionBuilder Add(Func<ProcessorExecutionDelegate, ProcessorExecutionDelegate> execution)
{
_components.Add(execution);
return this;
} public ProcessorExecutionBuilder Add(Func<Func<Task>, Task> middleware)
{
Add((next) => () =>
{
Func<Task> func = () => next();
return middleware(func);
});
return this;
} public ProcessorExecutionDelegate Build()
{
var next = (ProcessorExecutionDelegate)(() => Task.Run(() => { Console.WriteLine("Terminal Processor"); }));
_components.Reverse();
foreach (var item in _components)
{
next = item(next);
} return next;
}
}
3. 调用对象链
class Program
{
static void Main(string[] args)
{
var builder = new ProcessorExecutionBuilder();
builder.Add((next) =>
{
Console.WriteLine("Node1 Processor");
return next();
})
.Add((next) =>
{
Console.WriteLine("Node2 Processor");
return next();
}).Add((next) =>
{
Console.WriteLine("Node3 Processor");
return next();
}); builder.Build().Invoke();
Console.Read();
}
}
如何构造请求处理对象链(Pipeline)的更多相关文章
- 构造Json对象串工具类
import java.beans.IntrospectionException; import java.beans.Introspector; import java.beans.Property ...
- jQuery.buildFragment源码分析以及在构造jQuery对象的作用
这个方法在jQuery源码中比较靠后的位置出现,主要用于两处.1是构造jQuery对象的时候使用 2.是为DOM操作提供底层支持,这也就是为什么先学习它的原因.之前的随笔已经分析过jQuery的构造函 ...
- 9.19.1 反射构造Class对象
构造Class对象的三种方式: 第一种方式: (1)对于系统的类,必须写全名! (2)该方式会将.Cla ...
- js中的原型对象链
由于原型对象也是一个对象,它也有自己的原型对象并继承对象中的属性,这就是原型对象链:对象继承其原型对象,而原型对象继承它的原型对象,以此类推. 我们创建的每一个函数都有一个prototype(原型)属 ...
- jquery 1.7.2源码解析(二)构造jquery对象
构造jquery对象 jQuery对象是一个类数组对象. 一)构造函数jQuery() 构造函数的7种用法: 1.jQuery(selector [, context ]) 传入字符串参数:检查该字符 ...
- 4.构造Thread对象你也许不知道的几件事
1.Thread类对象只有在调用了start()方法之后,JVM虚拟机才会给我们创建一个真正的线程!否则就不能说是创建了线程!也就是说new Thread()之后,此时实际上在计算机底层,操作系统实际 ...
- jQuery源码分析-03构造jQuery对象-源码结构和核心函数
3. 构造jQuery对象 3.1源码结构 先看看总体结构,再做分解: (function( window, undefined ) { var jQuery = (function() { // 构 ...
- spring MVC之构造ModelAndView对象
spring MVC之构造ModelAndView对象 ---------- 构造ModelAndView对象 当控制器处理完请求时,通常会将包含视图名称或视图对象以及一些模型属性的ModelAndV ...
- Django中构造响应对象的方式
1 HttpResponse 可以使用django.http.HttpResponse来构造响应对象. HttpResponse(content=响应体, content_type=响应体数据类型, ...
随机推荐
- js进阶ajax函数封装(匿名函数作为参数传递)(封装函数引入文件的方式非常好用)
js进阶ajax函数封装(匿名函数作为参数传递)(封装函数引入文件的方式非常好用) 一.总结 2.匿名函数作为参数传递 二.js进阶ajax函数封装 ajax1.js function ajax(ur ...
- gerrit docker
修改项目配置文件 git clone ssh://admin@localhost:29418/All-Projects && scp -p -P 29418 admin@localho ...
- Hadoop基本原理之一:MapReduce 分类: A1_HADOOP 2014-08-17 19:26 1113人阅读 评论(0) 收藏
1.为什么需要Hadoop 目前,一块硬盘容量约为1TB,读取速度约为100M/S,因此完成一块硬盘的读取需时约2.5小时(写入时间更长).若把数据放在同一硬盘上,且全部数据均需要同一个程序进行处理, ...
- php 根据给定的年份和月份获取该年份该月份的起始和结束时间
function getShiJianChuo($nian=0,$yue=0){ if(empty($nian) || empty($yue)){ $now = time(); $nian = dat ...
- Django表单上传
任务描述:实现表单提交(上传文件) 1.项目目录: 2.源代码: regist.html <!DOCTYPE html> <html lang="en"> ...
- svn删除文件出错的经验总结
作者:朱金灿 来源:http://blog.csdn.net/clever101 今天有个同事在没有将工程从VS解决方案中移除的情况下使用svn对一个工程重命名,结果在提交时出错了,提示:没有匹配的可 ...
- C++省略号类型和参数个数不确定函数参数范例
声明:所有权利保留. 转载必须说明出处:http://blog.csdn.net/cartzhang/article/details/44203651 今天想写个宏定义,发现宏定义里也可以写不定参数, ...
- dbvisualizer 使用笔记
快捷键:CTRL+SHIFT+F 格式化选中的sql语句 导入导出数据操作 导入: 1.将Exel文件另存为csv文件 2.在dbvisualizer中点击开发数据库,如test_dev,然后在te ...
- 【codeforces 765B】Code obfuscation
[题目链接]:http://codeforces.com/contest/765/problem/B [题意] 让你把每个变量都依次替换成a,b,c,-.d这些字母; 且要按顺序先用a再用b-.c.d ...
- DDoS ATTACK PROCESSING APPARATUS AND METHOD IN OPENFLOW SWITCH
An OpenFlow switch in an OpenFlow environment includes an attack determination module to collect sta ...