zoukankan      html  css  js  c++  java
  • 如何设计出和 ASP.NET Core 中 Middleware 一样的 API 方法?

    由于笔者时间有限,无法写更多的说明文本,且主要是自己用来记录学习点滴,请谅解,下面直接贴代码了(代码中有一些说明):

    01-不好的设计

    代码:

    using System;
    
    namespace DesignSample
    {
        public class TrTemplateContext { public string TrAttrPrefix { get; set; } }
    
        class Program
        {
            public static void Main(string[] args)
            {
                AppendTimeForTrTag(c => string.Format("{0}-id="{1}"", c.TrAttrPrefix, "tr1"));
                //很显然,这是一个糟糕的设计,意味着每增加一个类似 AppendTimeForTrTag 的封装就
                //要增加很多类似于 AppendTimeForTrTag 的代码。参考 ASP.NET Core 中的 middleware
            }
    
            static void AppendTimeForTrTag(Func<TrTemplateContext, string> trTemplate)
            {/* 假设本方法来自于你们公司的A部门,通过封装,用于给<tr>标签固定附加 ng-time 属性 */
                Func<TrTemplateContext, string> trTimeTemplate = 
                    c => string.Format("{0}-time="{1}"", 
                            c.TrAttrPrefix,
                            DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
                Func<TrTemplateContext, string> trAllTemplate = trTimeTemplate;
                if(trTemplate != null)
                {
                    trAllTemplate = c => trTimeTemplate(c) + " " + trTemplate(c);
                }
                PrintTrTag(trAllTemplate);
            }
            
            static void PrintTrTag(Func<TrTemplateContext, string> trTemplate)
            {/* 假设本方法来自于ASP.NET Core内部。用于给<tr>标签附加一系列以 ng- 开头的属性 */
                string htmlTempl = "<tr {0}></tr>";
                string trInner = null;
                TrTemplateContext templContext = new TrTemplateContext { TrAttrPrefix = "ng" };
                if (trTemplate != null)
                {
                    trInner = trTemplate(templContext);
                }
                string fullHtml = string.Format(htmlTempl, trInner);
                Console.WriteLine(fullHtml);
            }
        }
    }

    运行结果:

    02-中间件设计(未提取公共代码)

    代码:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace DesignSample
    {
        public class TrAttrTemplateContext
        {
            public string TrAttrPrefix { get; set; }
    
            private StringBuilder trAttrBuilder = new StringBuilder();
    
            public void Add(string str)
            {
                if(trAttrBuilder.Length > 0)
                {
                    trAttrBuilder.Append(" ");
                }
                trAttrBuilder.Append(str);
            }
    
            public string GetAllString()
            {
                return trAttrBuilder.ToString();
            }
        }
        public delegate void RequestDelegate(TrAttrTemplateContext builder);
        public class TrAttrTemplateBuilder
        {
            private readonly List<Func<RequestDelegate, RequestDelegate>> _middlewares
                = new List<Func<RequestDelegate, RequestDelegate>>();
    
            public TrAttrTemplateBuilder Use(Func<RequestDelegate, RequestDelegate> middleware)
            {
                _middlewares.Add(middleware);
                return this;
            }
    
            public RequestDelegate Build()
            {
                _middlewares.Reverse();
                RequestDelegate next = c => { };
                foreach (var middleware in _middlewares)
                {
                    next = middleware(next);
                }
                return next;
            }
        }
    
        class Program
        {
            public static void Main(string[] args)
            {
                PrintTrTag(app => 
                    app.Use(AppendIdForTrTag) //给 tr 标签增加 ng-id 属性
                       .Use(AppendTimeForTrTag)  //给 tr 标签增加 ng-time 属性
                );
            }
    
            /* 假设本方法来自于你们公司的B部门,通过封装,用于给<tr>标签固定附加 ng-id 属性 */
            static RequestDelegate AppendIdForTrTag(RequestDelegate next) => context =>
            {
                context.Add($"{ context.TrAttrPrefix }-id="tr1"");
                next(context);
            };
    
            /* 假设本方法来自于你们公司的A部门,通过封装,用于给<tr>标签固定附加 ng-time 属性 */
            static RequestDelegate AppendTimeForTrTag(RequestDelegate next) => context =>
            {
                context.Add($"{ context.TrAttrPrefix }-time="{ DateTime.Now.ToString() }"");
                next(context);
            };
    
            /* 假设本方法来自于ASP.NET Core内部。用于给<tr>标签附加一系列以 ng- 开头的属性 */
            static void PrintTrTag(Func<TrAttrTemplateBuilder, TrAttrTemplateBuilder> trBuilderAction)
            {
                string htmlTempl = "<tr {0}></tr>";
                string trAttrInner = null;
                if (trBuilderAction != null)
                {
                    TrAttrTemplateBuilder builder = new TrAttrTemplateBuilder();
                    builder = trBuilderAction(builder);
                    if(builder != null)
                    {
                        TrAttrTemplateContext templContext = new TrAttrTemplateContext { TrAttrPrefix = "ng" };
                        builder.Build()(templContext);
                        trAttrInner = templContext.GetAllString();
                    }
                }
                string fullHtml = string.Format(htmlTempl, trAttrInner);
                Console.WriteLine(fullHtml);
            }
        }
    }

    运行截图:和 上图一样。

    03-中间件设计(已提取公共代码)

    代码:

    SpaceMiddlewareBuilder.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace DesignSample
    {
        /// <summary>
        /// 空格中间件生成器
        /// </summary>
        /// <typeparam name="TDelegate">委托的类型</typeparam>
        public class SpaceMiddlewareBuilder<TDelegate, TDelegateParam, TChild>
            where TDelegate: Delegate
            where TDelegateParam: SpaceMiddlewareContext
            where TChild : SpaceMiddlewareBuilder<TDelegate, TDelegateParam, TChild>,new()
        {
            private readonly List<Func<TDelegate, TDelegate>> _middlewares
                = new List<Func<TDelegate, TDelegate>>();
    
            private TDelegate _defaultAction;
    
            /// <summary>
            /// 构造一个空格中间件生成器
            /// </summary>
            /// <param name="defaultAction">默认执行的动作。无论是否有注册中间件,都会默认执行,除非在某一个中间件中拒绝调用 next(context)。不能为 NULL</param>
            public SpaceMiddlewareBuilder(TDelegate defaultAction)
            {
                this._defaultAction = defaultAction ?? throw new ArgumentNullException(nameof(defaultAction));
            }
    
            /// <summary>
            /// 使用中间件
            /// </summary>
            /// <param name="middleware"></param>
            /// <returns></returns>
            public TChild Use(Func<TDelegate, TDelegate> middleware)
            {
                _middlewares.Add(middleware);
                return (TChild)this;
            }
    
            /// <summary>
            /// 生成
            /// </summary>
            /// <returns></returns>
            public TDelegate Build()
            {
                _middlewares.Reverse();
                TDelegate next = this._defaultAction;
                foreach (var middleware in _middlewares)
                {
                    next = middleware(next);
                }
                return next;
            }
    
            /// <summary>
            /// 执行委托,返回附加的所有文本
            /// </summary>
            /// <param name="builderAction"></param>
            /// <param name="delegateParam"></param>
            /// <returns></returns>
            public string Execute(Func<TChild, TChild> builderAction, TDelegateParam delegateParam)
            {
                if(builderAction == null)
                {
                    return string.Empty;
                }
                TChild builder = new TChild();
                builder = builderAction(builder);
                if (builder == null)
                {
                    return string.Empty;
                }
                TDelegate tDelegate = builder.Build();
                if(tDelegate == null)
                {
                    return string.Empty;
                }
                tDelegate.DynamicInvoke(delegateParam);
                return delegateParam.GetAllText();
            }
        }
    }

    SpaceMiddlewareContext.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace DesignSample
    {
        /// <summary>
        /// 空格中间件上下文
        /// </summary>
        public class SpaceMiddlewareContext
        {
            private readonly StringBuilder _textBuilder;
    
            /// <summary>
            /// 构造函数
            /// </summary>
            public SpaceMiddlewareContext()
            {
                _textBuilder = new StringBuilder();
            }
    
            /// <summary>
            /// 增加一些文本字符串
            /// </summary>
            /// <param name="text"></param>
            public void Add(string text)
            {
                if (_textBuilder.Length > 0)
                {
                    _textBuilder.Append(" ");
                }
                _textBuilder.Append(text);
            }
    
            /// <summary>
            /// 获取到目前为止所有增加的文本字符串集合
            /// </summary>
            /// <returns></returns>
            public string GetAllText()
            {
                return _textBuilder.ToString();
            }
        }
    }

    Program.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace DesignSample
    {
        public class TrAttrTemplateContext : SpaceMiddlewareContext
        {
            public string TrAttrPrefix { get; set; }
        }
    
        public delegate void RequestDelegate(TrAttrTemplateContext arg);
    
        public class TrAttrTemplateBuilder : SpaceMiddlewareBuilder<RequestDelegate, TrAttrTemplateContext, TrAttrTemplateBuilder>
        {
            public TrAttrTemplateBuilder()
                : base(c => { c.Add($"{ c.TrAttrPrefix }-ending="true""); })
            {
    
            }
        }
    
        class Program
        {
            public static void Main(string[] args)
            {
                //PrintTrTag(null); //Test 1
                //PrintTrTag(app => app); //Test 2
                PrintTrTag(app =>
                    app.Use(AppendIdForTrTag) //给 tr 标签增加 ng-id 属性
                       .Use(AppendTimeForTrTag)  //给 tr 标签增加 ng-time 属性
                );//Test 3
            }
    
            /* 假设本方法来自于你们公司的B部门,通过封装,用于给<tr>标签固定附加 ng-id 属性 */
            static RequestDelegate AppendIdForTrTag(RequestDelegate next) => context =>
            {
                context.Add($"{ context.TrAttrPrefix }-id="tr1"");
                next(context);
            };
    
            /* 假设本方法来自于你们公司的A部门,通过封装,用于给<tr>标签固定附加 ng-time 属性 */
            static RequestDelegate AppendTimeForTrTag(RequestDelegate next) => context =>
            {
                context.Add($"{ context.TrAttrPrefix }-time="{ DateTime.Now.ToString() }"");
                next(context);
            };
    
            /* 假设本方法来自于ASP.NET Core内部。用于给<tr>标签附加一系列以 ng- 开头的属性 */
            static void PrintTrTag(Func<TrAttrTemplateBuilder, TrAttrTemplateBuilder> trBuilderAction)
            {
                string htmlTempl = "<tr {0}></tr>";
                string trAttrInner = new TrAttrTemplateBuilder().Execute(trBuilderAction, new TrAttrTemplateContext
                {
                    TrAttrPrefix = "ng"
                });
                string fullHtml = string.Format(htmlTempl, trAttrInner);
                Console.WriteLine(fullHtml);
            }
        }
    }

    谢谢浏览!

  • 相关阅读:
    【linux之web服务器apache】
    【linux工具之sed实例】
    【linux工具之strace】
    【linux工具之iptables 脚本】
    【linux工具之iptables】
    【Linux抓包工具之tcpdump】
    【抓包工具之wireshark】
    【Linux 基础服务之DNS】
    c语言
    sf
  • 原文地址:https://www.cnblogs.com/Music/p/use-middleware-design-in-csharp.html
Copyright © 2011-2022 走看看