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

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 > )
{
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 > )
{
_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);
}
}
}

谢谢浏览!

如何设计出和 ASP.NET Core 中 Middleware 一样的 API 方法?的更多相关文章

  1. ASP.NET Core中Middleware的使用

    https://www.cnblogs.com/shenba/p/6361311.html   ASP.NET 5中Middleware的基本用法 在ASP.NET 5里面引入了OWIN的概念,大致意 ...

  2. ASP.NET Core中,UseDeveloperExceptionPage扩展方法会吃掉异常

    在ASP.NET Core中Startup类的Configure方法中,有一个扩展方法叫UseDeveloperExceptionPage,如下所示: // This method gets call ...

  3. ASP.NET Core中使用自定义路由

    上一篇文章<ASP.NET Core中使用默认MVC路由>提到了如何使用默认的MVC路由配置,通过这个配置,我们就可以把请求路由到Controller和Action,通常情况下我们使用默认 ...

  4. 在 ASP.NET CORE 中使用 SESSION

    Session 是保存用户和 Web 应用的会话状态的一种方法,ASP.NET Core 提供了一个用于管理会话状态的中间件.在本文中我将会简单介绍一下 ASP.NET Core 中的 Session ...

  5. 在 ASP.NET CORE 中使用 SESSION (转载)

    Session 是保存用户和 Web 应用的会话状态的一种方法,ASP.NET Core 提供了一个用于管理会话状态的中间件.在本文中我将会简单介绍一下 ASP.NET Core 中的 Session ...

  6. ASP.NET Core WebApi使用Swagger生成api说明文档看这篇就够了

    引言 在使用asp.net core 进行api开发完成后,书写api说明文档对于程序员来说想必是件很痛苦的事情吧,但文档又必须写,而且文档的格式如果没有具体要求的话,最终完成的文档则完全取决于开发者 ...

  7. ASP.NET Core WebApi使用Swagger生成api

    引言 在使用asp.net core 进行api开发完成后,书写api说明文档对于程序员来说想必是件很痛苦的事情吧,但文档又必须写,而且文档的格式如果没有具体要求的话,最终完成的文档则完全取决于开发者 ...

  8. ASP.NET Core WebApi使用Swagger生成api说明文档

    1. Swagger是什么? Swagger 是一个规范和完整的框架,用于生成.描述.调用和可视化 RESTful 风格的 Web 服务.总体目标是使客户端和文件系统作为服务器以同样的速度来更新.文件 ...

  9. 【转】ASP.NET Core WebApi使用Swagger生成api说明文档看这篇就够了

    原文链接:https://www.cnblogs.com/yilezhu/p/9241261.html 引言 在使用asp.net core 进行api开发完成后,书写api说明文档对于程序员来说想必 ...

随机推荐

  1. 学习算法 - 表指针实现~ C++

    表指针实现.第二种方法是使用访问列表,模拟指针. 在我的理解中学习,它是创建一个节点数组,模拟存储装置,然后从中分配内存和释放内存. 但实际的内存没有被释放~ 下面的代码直接附着: // // mai ...

  2. 【matlab】安装 webcam 支持

    打开 matlab 命令行,输入 webcam,如果提示: 尚未安装 MATLAB Support Package for USB Webcams.打开支持包安装程序即可安装 Webcam Suppo ...

  3. 微信小程序唤起其他微信小程序 / 移动应用App唤起小程序

    微信小程序唤起其他微信小程序 / 移动应用App唤起小程序 1. 微信小程序唤起微信小程序 小程序唤起其他小程序很简单 先上链接 小程序跳转小程序 Navigator组件 推荐使用 小程序跳转小程序 ...

  4. 《⑨也懂系列:MinGW-w64安装教程》著名C/C++编译器GCC的Windows版本(MinGW-w64在安装的时候可以选择版本,有图,一步一步)

    发布日期 2016年10月31日 分类 教程 标签 编程.软件 前言<⑨也懂系列:MinGW-w64安装教程>这篇文章由 rsreland (http://rsreland.net)于 2 ...

  5. 线性方程组的求解(C++)

    1. 最佳求解方案 Most efficient way to solve a system of linear equations 求解形如 Ax=b 的最佳方式 将 A 分解为三角矩阵,A=M1⋅ ...

  6. Android实现图片滚动控件,含页签功能,让你的应用像淘宝一样炫起来

    首先题外话,今天早上起床的时候,手滑一下把我的手机甩了出去,结果陪伴我两年半的摩托罗拉里程碑一代就这么安息了,于是我今天决定怒更一记,纪念我死去的爱机. 如果你是网购达人,你的手机上一定少不了淘宝客户 ...

  7. 1-6 WebAPI基础和演示项目搭建

    启动项目的时候 在控制台用dotnet MsgService.dll的方式启动. 在program.cs文件下做如下修改: 实现在控制台 自定义ip和端口,修改之后有将项目重新生成,在控制台启动项目, ...

  8. PAMIE- Python实现IE自动化的模块

    PAMIE- Python实现IE自动化的模块(附 网易注册代码) 收藏 安装: 今晚弄了一下.已经成功导入PAMIE.具体步骤如下 1.假如你要用PAM30那就就得去下个Python 3.0安装.因 ...

  9. 怎样从一名程序员过度到项目经理(整理自csdn论坛) 选择自 whoopee 的 Blog

    1.从程序员到PM,是一条脱变的路,事实上程序员走的路最终不应该是项目经理.首先有一点需要明白的就是,一定规模的项目中,项目经理不需要太懂技术,他可以是一知半解.项目经理的任务不是在技术方面,技术相关 ...

  10. 跨进程调用Service(AIDL Service)

    1.什么是aidl:aidl这是 Android Interface definition language的缩写,一看就明确.它是一种android内部进程通信接口的描写叙述语言.通过它我们能够定义 ...