zoukankan      html  css  js  c++  java
  • 链式调用

    用设计模式、AOP能将一个方法/函数包裹起来,并且插入额外的逻辑行为,不过动作比较大,不是很灵活,下面介绍一种链式调用方法来封装的代码,完成后能实现如下的链式调用:

    public class BO
            {
                public bool Add(string msg)
                {
                    Console.WriteLine("Add");
    
                    if (msg == null)
                        throw new Exception();
    
                    return true;
                }
            }
    
            static void Main(string[] args)
            {
                BO bo=new BO();
    
                Pipeline<string, bool> p = Pipeline.Wrap<string, bool>(bo.Add)
                            .BeforeExecute(m=>Console.WriteLine("before execute"))
                            .AfterExecute((m, n) => Console.WriteLine("after execute1"))
                            .AfterExecute((m, n) => Console.WriteLine("after execute2"))
                            .Success((m, n) => Console.WriteLine("success"))
                            .Fail((m, n) => Console.WriteLine("fail"))
                            .Final((m, n) => Console.WriteLine("final"));
    
    
                Console.WriteLine("Result: "+p.Execute("testing").Result);
    
                Console.WriteLine();
                Console.WriteLine();
    
                Console.WriteLine("Result: " + p.Execute(null).Result);
    
                Console.ReadKey();
            }

     运行图:

     注意:这个封装会对目标业务函数加入try/catch来得到业务是否成功执行。

    实现起来比较简单,就是每个函数返回自身,如下:

    public static class Pipeline//这里只实现了2个泛型,可以增加很多个(这点比较麻烦)
        {
            public static Pipeline<TIN, TOUT> Wrap<TIN, TOUT>(Func<TIN, TOUT> method)
            {
                Pipeline<TIN, TOUT> p = new Pipeline<TIN, TOUT>(method);
                return p;
            }
    
            public static Pipeline<TIN1, TIN2, TOUT> Wrap<TIN1, TIN2, TOUT>(Func<TIN1, TIN2, TOUT> method)
            {
                Pipeline<TIN1, TIN2, TOUT> p = new Pipeline<TIN1, TIN2, TOUT>(method);
                return p;
            }
        }

     最终返回的结果对象:

    public struct PipelineResult<TOUT>
        {
            /// <summary>
            /// 目标核心函数返回值
            /// </summary>
            public TOUT Result { get; set; }
    
            /// <summary>
            /// 是否存在异常
            /// </summary>
            public bool ExceptionExists { get; set; }
    
            /// <summary>
            /// 具体的异常
            /// </summary>
            public Exception Exception { get; set; }
        }

     只有一个输入参数的Wrapper:

    public class Pipeline<TIN, TOUT>
        {
            private Func<TIN, TOUT> method2Execute;
            private List<Action<TIN>> beforeExecuteActions = new List<Action<TIN>>();
            private List<Action<TIN, TOUT>> afterExecuteActions = new List<Action<TIN, TOUT>>();
            private Action<TIN, TOUT> finalAction;
            private List<Action<TIN, TOUT>> successActions = new List<Action<TIN, TOUT>>();
            private List<Action<TIN, TOUT>> failActions = new List<Action<TIN, TOUT>>();
    
            public Pipeline(Func<TIN, TOUT> method)
            {
                this.method2Execute = method;
            }
    
            public Pipeline<TIN, TOUT> BeforeExecute(Action<TIN> action)
            {
                beforeExecuteActions.Add(action);
    
                return this;
            }
    
            public Pipeline<TIN, TOUT> AfterExecute(Action<TIN, TOUT> action)
            {
                afterExecuteActions.Add(action);
    
                return this;
            }
    
            public Pipeline<TIN, TOUT> Final(Action<TIN, TOUT> action)
            {
                this.finalAction = action;
    
                return this;
            }
    
            public Pipeline<TIN, TOUT> Success(Action<TIN, TOUT> action)
            {
                successActions.Add(action);
    
                return this;
            }
    
            public Pipeline<TIN, TOUT> Fail(Action<TIN, TOUT> action)
            {
                failActions.Add(action);
    
                return this;
            }
    
            public PipelineResult<TOUT> Execute(TIN argument)
            {
                PipelineResult<TOUT> result = new PipelineResult<TOUT>();
    
                foreach (var action in this.beforeExecuteActions)
                    action.Invoke(argument);
    
                try
                {
                    result.Result = this.method2Execute.Invoke(argument);
                    result.ExceptionExists = false;
                    result.Exception = null;
                }
                catch (Exception ex)
                {
                    result.ExceptionExists = true;
                    result.Exception = ex;
                }
    
                foreach (var action in this.afterExecuteActions)
                    action.Invoke(argument, result.Result);
    
                if (!result.ExceptionExists)
                {
                    foreach (var action in this.successActions)
                        action.Invoke(argument, result.Result);
                }
                else
                {
                    foreach (var action in this.failActions)
                        action.Invoke(argument, result.Result);
                }
    
                if (this.finalAction != null)
                    this.finalAction.Invoke(argument, result.Result);
    
                return result;
            }
        }

    支持2个输入参数的Wrapper:

    public class Pipeline<TIN1, TIN2, TOUT>
        {
            private Func<TIN1, TIN2, TOUT> method2Execute;
            private List<Action<TIN1, TIN2>> beforeExecuteActions = new List<Action<TIN1, TIN2>>();
            private List<Action<TIN1, TIN2, TOUT>> afterExecuteActions = new List<Action<TIN1, TIN2, TOUT>>();
            private Action<TIN1, TIN2, TOUT> finalAction;
            private List<Action<TIN1, TIN2, TOUT>> successActions = new List<Action<TIN1, TIN2, TOUT>>();
            private List<Action<TIN1, TIN2, TOUT>> failActions = new List<Action<TIN1, TIN2, TOUT>>();
    
            public Pipeline(Func<TIN1, TIN2, TOUT> method)
            {
                this.method2Execute = method;
            }
    
            public Pipeline<TIN1, TIN2, TOUT> BeforeExecute(Action<TIN1, TIN2> action)
            {
                beforeExecuteActions.Add(action);
    
                return this;
            }
    
            public Pipeline<TIN1, TIN2, TOUT> AfterExecute(Action<TIN1, TIN2, TOUT> action)
            {
                afterExecuteActions.Add(action);
    
                return this;
            }
    
            public Pipeline<TIN1, TIN2, TOUT> Final(Action<TIN1, TIN2, TOUT> action)
            {
                this.finalAction = action;
    
                return this;
            }
    
            public Pipeline<TIN1, TIN2, TOUT> Success(Action<TIN1, TIN2, TOUT> action)
            {
                successActions.Add(action);
    
                return this;
            }
    
            public Pipeline<TIN1, TIN2, TOUT> Fail(Action<TIN1, TIN2, TOUT> action)
            {
                failActions.Add(action);
    
                return this;
            }
    
            public PipelineResult<TOUT> Execute(TIN1 argument1, TIN2 argument2)
            {
                PipelineResult<TOUT> result = new PipelineResult<TOUT>();
    
                foreach (var action in this.beforeExecuteActions)
                    action.Invoke(argument1, argument2);
    
                try
                {
                    result.Result = this.method2Execute.Invoke(argument1, argument2);
                    result.ExceptionExists = false;
                    result.Exception = null;
                }
                catch (Exception ex)
                {
                    result.ExceptionExists = true;
                    result.Exception = ex;
                }
    
                foreach (var action in this.afterExecuteActions)
                    action.Invoke(argument1, argument2, result.Result);
    
                if (!result.ExceptionExists)
                {
                    foreach (var action in this.successActions)
                        action.Invoke(argument1, argument2, result.Result);
                }
                else
                {
                    foreach (var action in this.failActions)
                        action.Invoke(argument1, argument2, result.Result);
                }
    
                if (this.finalAction != null)
                    this.finalAction.Invoke(argument1, argument2, result.Result);
    
                return result;
            }
        }

    支持更多输入参数的?不要返回值的?自己搞定吧。 

    尽管这个模式很简单,但是只要扩展一下,就能做简单的复合业务逻辑,比如xml文件来配置,最终组合成复合业务,很有潜力的一个模式。 

  • 相关阅读:
    学习OpenStack之(6):Neutron 深入学习之 OVS + GRE 之 Compute node 篇
    学习OpenStack之(5):在Mac上部署Juno版本OpenStack 四节点环境
    学习OpenStack之 (3):Devstack Screen 使用技巧
    C语言 fread()与fwrite()函数说明与示例
    win C/C++程序通过Get方式获取网页源代码
    ubuntu/wireshark: There are no interfaces on which a capture can be done.故障解决
    [转]VS2010快捷键
    C/C++/Java 程序计时功能函数
    程序设计中使用的那些共享方法或者技术
    GPU/CUDA程序初体验 向量加法
  • 原文地址:https://www.cnblogs.com/aarond/p/Pipeline.html
Copyright © 2011-2022 走看看