我想知道如何在我的应用程序中使用像asp.net core这样的中间件架构?
这个目标需要哪种模式?
是否有任何像这样的设计参考添加新功能和...?
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
app.UseBrowserLink();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles();
app.UseIdentity();
// Add external authentication middleware below. To configure them please see http://go.microsoft.com/fwlink/?LinkID=532715
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
Run Code Online (Sandbox Code Playgroud)
使用非常简单的Configure方法,我们可以向应用程序添加新功能如何实现这样的功能?
我要做的第一件事是阅读中间件 - Asp.Net文档
这将有助于了解中间件的使用方式以及实现自定义中间件所需遵循的实践.
直接取自docs
中间件是组装到应用程序管道中以处理请求和响应的软件组件.每个组件选择是否将请求传递给管道中的下一个组件,并且可以在管道中调用下一个组件之前和之后执行某些操作.请求委托用于构建请求管道.请求委托处理每个HTTP请求.
现在,这表明它允许组件处理请求和响应.中间件按照添加到应用程序中间件集合的顺序执行.
app.UseStaticFiles(); 添加middlware来处理静态文件(图像,CSS,脚本等).
现在假设您希望在管道中添加自己的处理,您可以创建一个中间件类作为下面的示例.
public class GenericMiddleware
{
public GenericMiddleware(RequestDelegate next)
{
_next = next;
}
readonly RequestDelegate _next;
public async Task Invoke(HttpContext context, IHostingEnvironment hostingEnviroment)
{
//do something
await _next.Invoke(context);
}
}
Run Code Online (Sandbox Code Playgroud)
这里有一些有趣的点.首先,构造函数接受一个RequestDelegate基本上(但不完全是)将被调用的下一个中间件对象.
接下来我们实现自己的Invoke方法.此方法应该HttpContext作为参数使用,并且还允许从IoC容器(在我的示例中为IHostingEnvironment实例)中注入其他依赖项.
然后,此方法执行它需要执行,然后调用代码 await _next.Invoke(context);执行该RequestDelegate呼叫下一个中间件类.
现在将其添加到应用程序中间件中,您只需调用即可
app.UseMiddleware<GenericMiddleware>();在您Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)的startup.cs文件中的方法.
或者创建一个简单的扩展方法.
public static class GenericMiddlewareExtensions
{
public static IApplicationBuilder UseGenericMiddleware(this IApplicationBuilder app)
{
app.UseMiddleware<GenericMiddleware>();
return app;
}
}
Run Code Online (Sandbox Code Playgroud)
然后调用哪个 app.UseGenericMiddleware();
现在,您实现自己的中间件的方式和原因取决于您.但是如上所述,RequestDelegate如果中间件没有,则由中间件调用,然后停止请求.
以下是我的一个项目中的示例,该项目检查数据库是否已安装.如果它没有将请求重定向回安装页面.
public class InstallationMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger _logger;
public InstallationMiddleware(RequestDelegate next, ILoggerFactory loggerFactory)
{
_next = next;
_logger = loggerFactory.CreateLogger<InstallationMiddleware>();
}
public async Task Invoke(HttpContext context)
{
_logger.LogInformation("Handling request: " + context.Request.Path);
if (context != null && !DatabaseHelper.IsDatabaseInstalled())
{
if (!context.Request.Path.ToString().ToLowerInvariant().StartsWith("/installation"))
{
context.Response.Redirect("/installation");
return;
}
}
await _next.Invoke(context);
_logger.LogInformation("Finished handling request.");
}
}
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,!DatabaseHelper.IsDatabaseInstalled()我们是否重定向响应但不调用_next RequestDelegate.
文档再次说明了一切.
我为正在处理的项目制作了一个简单的原型实现,该实现与ASP.NET Core无关,因此,不了解其体系结构或实现的人可能会更容易理解该概念。
这里发挥作用的设计模式称为 责任链”模式。
因此,我们需要做的第一件事就是为应用程序定义委托:
public delegate void InputDelegate(char key);
Run Code Online (Sandbox Code Playgroud)
然后我们需要一些东西来消耗它,因此这是一个非常简单的事件/主循环实现:
internal class TerminalHost
{
private InputDelegate _inputDelegate;
public TerminalHost()
{
// Initializes the first delegate to be invoked in the chain.
_inputDelegate = Console.Write;
}
internal void Start()
{
CancellationTokenSource tokenSource = new CancellationTokenSource();
while (!tokenSource.IsCancellationRequested) {
ConsoleKeyInfo keyInfo = Console.ReadKey();
_inputDelegate(keyInfo.KeyChar);
}
}
/// <summary>
/// Adds the middleware to the invocation chain.
/// </summary>
/// <param name="middleware"> The middleware to be invoked. </param>
/// <remarks>
/// The middleware function takes an instance of delegate that was previously invoked as an input and returns the currently invoked delegate instance as an output.
/// </remarks>
internal void Use(Func<InputDelegate, InputDelegate> middleware)
{
// Keeps a reference to the currently invoked delegate instance.
_inputDelegate = middleware(_inputDelegate);
}
}
Run Code Online (Sandbox Code Playgroud)
最后,我们需要创建一个实例 TerminalHost该类并调用该Use方法,这样将类似于以下内容:
class Program
{
static void Main(string[] args)
{
TerminalHost terminal = new TerminalHost();
terminal.Use(next => ch => {
Console.WriteLine(ch);
next(ch);
});
terminal.Start();
}
}
Run Code Online (Sandbox Code Playgroud)
我希望这是有道理的,并且对外面的人有帮助!:)
| 归档时间: |
|
| 查看次数: |
4542 次 |
| 最近记录: |