iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >C#中管道式编的示例分析
  • 532
分享到

C#中管道式编的示例分析

2023-06-20 15:06:53 532人浏览 薄情痞子
摘要

这篇文章主要介绍C#中管道式编的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!前言在 C# 编程中,管道式编程(Pipeline Style programming)其实存在已久,最明显的就是我们经常使用的

这篇文章主要介绍C#中管道式编的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!

前言

在 C# 编程中,管道式编程(Pipeline Style programming)其实存在已久,最明显的就是我们经常使用的 LINQ。在进入 Dotnetcore 世界后, 这种编程方式就更加明显,比如各种中间件的使用。通过使用这种编程方式,大大提高了代码的可维护性,优化了的业务的组合方式。

管道式编程具有如下优点:

  • 创建一个流畅的编程范例,将语句转换为表达式并将它们链接在一起

  • 用线性排序替换代码嵌套

  • 消除变量声明 - 甚至不需要 var

  • 提供某种形式的可变不变性和范围隔离

  • 将结构代码编写成具有明确职责的小 lambda 表达式

  • ......

基础实现

在该示例中,我们通过构建一个 double->int->string 的类型转换的管道来将一个目标数据最终转化为一个字符串

  • 首先,我们需要定义一个功能接口,用于约束每个功能函数的具体实现,示例代码如下所示:

public interface IPipelineStep<INPUT, OUTPUT>{    OUTPUT Process(INPUT input);}
  • 然后,我们定义两个类型转换的功能类,继承并实现上述接口,示例代码如下所示:

public class DoubleToIntStep : IPipelineStep<double, int>{    public int Process(double input)    {        return Convert.ToInt32(input);    }}public class IntToStringStep : IPipelineStep<int, string>{    public string Process(int input)    {        return input.ToString();    }}
  • 接着,定义一个扩展函数,用于连接上述的各个功能函数,示例代码如下所示:

public static class PipelineStepExtensions{    public static OUTPUT Step<INPUT, OUTPUT>(this INPUT input, IPipelineStep<INPUT, OUTPUT> step)    {        return step.Process(input);    }}
  • 最后,我们就可以构建一个完整的管道,用于我们的数据类型转换,示例代码如下所示:

class Program{    static void Main(string[] args)    {        double input = 1024.1024;        // 构建并使用管道        string result = input.Step(new DoubleToIntStep())                             .Step(new IntToStringStep());        Console.WriteLine(result);    }}

此时,我们成功将一个 double 类型的数据转化为了 string 类型。通过介绍上述示例,我们可以简单将管道式编程概括为:定义功能接口 -> 实现功能函数 -> 组装功能函数 。

依赖注入

上述代码在一般的情况下是可以正常运行的,但是如果希望以 依赖注入(DI) 的方式注入的话,我们就需要将我们的管道组装进行封装,方便作为一个统一的服务注入到系统中。

  • 首先,我们需要定义一个抽线类,用于管道组装的抽象封装,示例代码如下所示:

public abstract class Pipeline<INPUT,OUTPUT>{    public Func<INPUT, OUTPUT> PipelineSteps { get; protected set; }    public OUTPUT Process(INPUT input)    {        return PipelineSteps(input);    }}
  • 然后,我们就可以创建一个继承上述抽象类的具体管道组装类,示例代码如下所示:

public class TrivalPipeline : Pipeline<double, string>{    public TrivalPipeline()    {        PipelineSteps = input => input.Step(new DoubleToIntSetp())                                      .Step(new IntToStringStep());    }}

最后,我们可以将 TrivalPipeline 这个具体的管道注入到我们的系统中。同样的,我们也可以直接使用,示例代码如下所示:

class Program{    static void Main(string[] args)    {        double input = 1024.1024;        // 需要安装 Microsoft.Extensions.DependencyInjection        var services = new ServiceCollection();        services.AddTransient<TrivalPipeline>();        var  provider = services.BuildServiceProvider();        var trival = provider.GetService<TrivalPipeline>();        string result = trival.Process(input);        Console.WriteLine(result);    }}

条件式组装

上述两个示例代码展示的管道组装式不带任何条件限制的, 无论参数是否合法都是这样组装进管道,但是在实际的开发过程中,我们需要对一定的业务模块进行条件性组装,所以这个时候我们就需要完善一下我们的代码。

首先,我们需要修改上面的 Pipeline<INPUT,OUTPUT> 类,使其继承 IPipelineStep<INPUT, OUTPUT> 接口,示例代码如下所示:

public abstract class Pipeline<INPUT, OUTPUT> : IPipelineStep<INPUT, OUTPUT>{    public Func<INPUT, OUTPUT> PipelineSteps { get; protected set; }    public OUTPUT Process(INPUT input)    {        return PipelineSteps(input);    }}
  • 然后,我们定义一个带条件的管道装饰器类,示例代码如下所示:

public class OptionalStep<INPUT, OUTPUT> : IPipelineStep<INPUT, OUTPUT> where INPUT : OUTPUT{    private readonly IPipelineStep<INPUT, OUTPUT> _step;    private readonly Func<INPUT, bool> _choice;    public OptionalStep(Func<INPUT,bool> choice,IPipelineStep<INPUT,OUTPUT> step)    {        _choice = choice;        _step = step;    }    public OUTPUT Process(INPUT input)    {        return _choice(input) ? _step.Process(input) : input;    }}
  • 接着,我们定义一个新的功能类和支持条件判断的管道包装类,示例代码如下所示:

public class ThisStepIsOptional : IPipelineStep<double, double>{    public double Process(double input)    {        return input * 10;    }}public class PipelineWithOptionalStep : Pipeline<double, double>{    public PipelineWithOptionalStep()    {        // 当输入参数大于 1024,执行 ThisStepIsOptional() 功能        PipelineSteps = input => input.Step(new OptionalStep<double, double>(i => i > 1024, new ThisStepIsOptional()));    }}
  • 最后,我们可以使用如下方式进行测试

class Program{    static void Main(string[] args)    {        PipelineWithOptionalStep step = new PipelineWithOptionalStep();        Console.WriteLine(step.Process(1024.1024));  // 输出 10241.024        Console.WriteLine(step.Process(520.520));    // 输出 520.520    }}

事件监听

有的时候,我们希望在我们管道中执行的每一步,在开始和结束时,上层模块都能获得相应的事件通知,这个时候,我们就需要需改一下我们的管道包装器,使其支持这个需求。

首先,我们需要实现一个支持事件监听的具体功能类,示例代码代码如下所示:

public class EventStep<INPUT, OUTPUT> : IPipelineStep<INPUT, OUTPUT>{    public event Action<INPUT> OnInput;    public event Action<OUTPUT> OnOutput;    private readonly IPipelineStep<INPUT, OUTPUT> _innerStep;    public EventStep(IPipelineStep<INPUT,OUTPUT> innerStep)    {        _innerStep = innerStep;    }    public OUTPUT Process(INPUT input)    {        OnInput?.Invoke(input);        var output = _innerStep.Process(input);        OnOutput?.Invoke(output);        return output;    }}
  • 然后,我们需要定义一个能够传递事件参数的管道包装器类,示例代码如下所示:

public static class PipelineStepEventExtensions{    public static OUTPUT Step<INPUT, OUTPUT>(this INPUT input, IPipelineStep<INPUT, OUTPUT> step, Action<INPUT> inputEvent = null, Action<OUTPUT> outputEvent = null)    {        if (inputEvent != null || outputEvent != null)        {            var eventDecorator = new EventStep<INPUT, OUTPUT>(step);            eventDecorator.OnInput += inputEvent;            eventDecorator.OnOutput += outputEvent;            return eventDecorator.Process(input);        }        return step.Process(input);    }}
  • 最后,上层调用就相对简单很多,示例代码如下所示:

public class DoubleStep : IPipelineStep<int, int>{    public int Process(int input)    {        return input * input;    }}class Program{    static void Main(string[] args)    {        var input = 10;        Console.WriteLine($"Input Value:{input}[{input.GetType()}]");        var pipeline = new EventStep<int, int>(new DoubleStep());        pipeline.OnInput += i => Console.WriteLine($"Input Value:{i}");        pipeline.OnOutput += o => Console.WriteLine($"Output Value:{o}");        var output = pipeline.Process(input);        Console.WriteLine($"Output Value: {output} [{output.GetType()}]");        Console.WriteLine("\r\n");        //补充:使用扩展方法进行调用        Console.WriteLine(10.Step(new DoubleStep(), i =>         {            Console.WriteLine($"Input Value:{i}");        },         o =>         {            Console.WriteLine($"Output Value:{o}");        }));    }}

输出结果如下图所示:

C#中管道式编的示例分析

可迭代执行

可迭代执行是指当我们的管道中注册了多个功能模块时,不是一次性执行完所以的功能模块,而是每次只执行一个功能,后续功能会在下次执行该管道对应的代码块时接着执行,直到该管道中所有的功能模块执行完毕为止。该特性主要是通过 yield return 来实现。

首先,我们需要实现一个该特性的管道包装器类,示例代码如下所示:

public class LoopStep<INPUT, OUTPUT> : IPipelineStep<IEnumerable<INPUT>, IEnumerable<OUTPUT>>{    private readonly IPipelineStep<INPUT, OUTPUT> _internalStep;    public LoopStep(IPipelineStep<INPUT,OUTPUT> internalStep)    {        _internalStep = internalStep;    }    public IEnumerable<OUTPUT> Process(IEnumerable<INPUT> input)    {        foreach (INPUT item in input)        {            yield return _internalStep.Process(item);        }        //等价于下述代码段        //return from INPUT item in input        //       select _internalStep.Process(item);    }}
  • 然后,定义一个支持上述类型的功能组装的扩展方法,示例代码如下所示:

public static class PipelineStepLoopExtensions{    public static IEnumerable<OUTPUT> Step<INPUT, OUTPUT>(this IEnumerable<INPUT> input, IPipelineStep<INPUT, OUTPUT> step)    {        LoopStep<INPUT, OUTPUT> loopDecorator = new LoopStep<INPUT, OUTPUT>(step);        return loopDecorator.Process(input);    }}
  • 最后,上层调用如下所示:

class Program{    static void Main(string[] args)    {        var list = Enumerable.Range(0, 10);        foreach (var item in list.Step(new DoubleStep()))        {            Console.WriteLine(item);        }    }}

以上是“C#中管道式编的示例分析”这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注编程网精选频道!

--结束END--

本文标题: C#中管道式编的示例分析

本文链接: https://www.lsjlt.com/news/297570.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • C#中管道式编的示例分析
    这篇文章主要介绍C#中管道式编的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!前言在 C# 编程中,管道式编程(Pipeline Style programming)其实存在已久,最明显的就是我们经常使用的 ...
    99+
    2023-06-20
  • Linux中管道及有名管道的示例分析
    小编给大家分享一下Linux中管道及有名管道的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!管道及有名管道     ...
    99+
    2023-06-13
  • Redis中管道机制的示例分析
    这篇文章将为大家详细讲解有关Redis中管道机制的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。Pipeline简介Redis客户端执行一条命令:发送命令命令排队...
    99+
    2024-04-02
  • linux中C语言开发管道通信的示例分析
    这篇文章主要介绍了linux中C语言开发管道通信的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。linux C语言开发管道通信   Linux系统...
    99+
    2023-06-09
  • Shell中管道重定向的示例分析
    小编给大家分享一下Shell中管道重定向的示例分析,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!1.8.1 匿名管道"|"管道符号意如其名,类似管道一样将管道入口的数据通过管道传递给管道出口。管道是为了...
    99+
    2023-06-09
  • Linux中重定向和管道的示例分析
    这篇文章主要介绍了Linux中重定向和管道的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。对shell有一定了解的人都知道,管道和重定向是 Linux 中非常实用的 ...
    99+
    2023-06-27
  • linux中管道及重定向的示例分析
    这篇文章主要介绍了linux中管道及重定向的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。在linux系统中,大多数命令很简单,很少出现复杂功能的命令,每个命令往往实...
    99+
    2023-06-12
  • Angular中的管道实例分析
    本篇内容介绍了“Angular中的管道实例分析”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!什么是管道(P...
    99+
    2024-04-02
  • Netty分布式pipeline管道传播outBound事件的示例分析
    这篇文章将为大家详细讲解有关Netty分布式pipeline管道传播outBound事件的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。outbound事件传输流程在我们业务代码中, 有可能使用w...
    99+
    2023-06-29
  • C++中内存管理的示例分析
    这篇文章将为大家详细讲解有关C++中内存管理的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。概述内存管理的原理庞大而复杂,然而这些都被操作系统进行了封装,并对外预留了API,这些api被c++调用...
    99+
    2023-06-25
  • Shell中管道及执行顺序的示例分析
    这篇文章主要介绍Shell中管道及执行顺序的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!1、基本概念 a、I/O重定向通常与 FD有关,shell的FD通常为10个,即 0~9; b、常用FD有3个,为0(...
    99+
    2023-06-09
  • c#中异步编程的示例分析
    这篇文章给大家分享的是有关c#中异步编程的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。一、什么算异步?  广义来讲,两个工作流能同时进行就算异步,例如,CPU与外设之间的工作流就是异步的。在面向服务的系...
    99+
    2023-06-14
  • linux中Bash管道与重定向的示例分析
    这篇文章主要为大家展示了“linux中Bash管道与重定向的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“linux中Bash管道与重定向的示例分析”这篇文章吧。管道与重定向Bash的标...
    99+
    2023-06-27
  • Netty分布式pipeline管道异常传播事件的示例分析
    这篇文章主要介绍了Netty分布式pipeline管道异常传播事件的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。传播异常事件简单的异常处理的场景@Overridep...
    99+
    2023-06-29
  • C/C++内存管理的示例分析
    这篇文章主要介绍了C/C++内存管理的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。C/C++赋予程序员管理内存的自由,是C/C++语言特色,虽然这引入了复杂度和危险...
    99+
    2023-06-15
  • C#单例模式的示例分析
    这篇文章给大家分享的是有关C#单例模式的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。单例模式也是创建型模式的一种,也是23种设计模式中比较简单的一种。见名思意,在整个软件系统中,只有某个类型的一个对象,...
    99+
    2023-06-29
  • js中函数式编程的示例分析
    这篇文章主要为大家展示了“js中函数式编程的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“js中函数式编程的示例分析”这篇文章吧。(1)平常写的函数大多...
    99+
    2024-04-02
  • C++内嵌汇编的示例分析
    这篇文章主要为大家展示了“C++内嵌汇编的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“C++内嵌汇编的示例分析”这篇文章吧。汇编语言汇编语言是一种功能很强的程序设计语言,也是利用了计算...
    99+
    2023-06-28
  • C++模板编程的示例分析
    这篇文章主要为大家展示了“C++模板编程的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“C++模板编程的示例分析”这篇文章吧。模板初阶泛型编程在计算机程序设计领域,为了避免因数据类型的不...
    99+
    2023-06-25
  • C#异步编程的示例分析
    小编给大家分享一下C#异步编程的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!异步编程在处理并发方面被使用的越来越多,之所以说上面一句话,是为了区分多线程...
    99+
    2023-06-17
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作