在 .net 核心应用程序启动中结合使用 MapWhen 和 ApplicationBuilder?
Using a combination of MapWhen and ApplicationBuilder in .net core app startup?
是否可以部分分支启动?
举个例子,是否可以这样:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.AlwaysUseThisMiddleware();
app.MapWhen(conditionA, appBuilder => {appBuilder.SometimesUseThisOne;})
app.MapWhen(conditionB, appBuilder => {appBuilder.SometimesUseThisOtherOne;})
或者我需要把 AlwaysUseThisMiddleware
放在每个分支中吗?像这样:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.MapWhen(conditionA, appBuilder =>
{
appBuilder.AlwaysUseThisMiddleware(); // Duplicated
appBuilder.SometimesUseThisOne;
)
app.MapWhen(conditionB, appBuilder =>
{
appBuilder.AlwaysUseThisMiddleware(); // Duplicated
appBuilder.SometimesUseThisOtherOne;
)
简答:
是的。它将按您的预期工作。
其实我们在Use()
一系列中间件的时候,就是在注册一系列的中间件,处理请求的时候会依次调用这些中间件。
MapWhen()
方法只不过是辅助方法 that invokes the Use()
. What MapWhen(predicate,configFn)
does is to registering something that runs as below :
if (predicate(context)){
await branch(context);
} else {
await _next(context);
}
因此,当我们调用 MapWhen()
时,我们正在注册另一个分支处理的中间件。
例如:
app.UseMiddleware<AlwaysUseThisMiddleware>();
app.MapWhen(ctx=>ctx.Request.Query["a"]=="1", appBuilder =>{
appBuilder.UseMiddleware<SometimesUseThisOne>();
});
app.MapWhen(ctx=>ctx.Request.Query["b"]=="1", appBuilder =>{
appBuilder.UseMiddleware<SometimesUseThisOtherOne>();
})
// ...
基本上,此代码按以下方式运行:
call `AlwaysUseThisMiddleware`;
////////////////////////////////////
if (ctx.Request.Query["a"]=="1"){
call SometimesUseThisOne ;
} else {
//------------------------------------------
if (ctx.Request.Query["b"]=="1"){
call SometimesUseThisOtherOne ;
} else {
//##################################################
await _next(context); // call other middlewares ...
//##################################################
}
//-----------------------------------------
}
////////////////////////////////////
或者如果你喜欢也可以重写如下:
call `AlwaysUseThisMiddleware` middleware
if(ctx.Request.Query["a"]=="1") // go to branch 1
call `SometimesUseThisOne` middleware
else if (ctx.Request.Query["b"]=="1") // go to branch 2
call `SometimesUseThisOtherOne` middleware
else :
...
注意这里的分支被翻译成 else if
而不是 if
。并且中间件 AlwaysUseThisMiddleware
总是在 branch1 & branch2 之前被调用。
是否可以部分分支启动?
举个例子,是否可以这样:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.AlwaysUseThisMiddleware();
app.MapWhen(conditionA, appBuilder => {appBuilder.SometimesUseThisOne;})
app.MapWhen(conditionB, appBuilder => {appBuilder.SometimesUseThisOtherOne;})
或者我需要把 AlwaysUseThisMiddleware
放在每个分支中吗?像这样:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.MapWhen(conditionA, appBuilder =>
{
appBuilder.AlwaysUseThisMiddleware(); // Duplicated
appBuilder.SometimesUseThisOne;
)
app.MapWhen(conditionB, appBuilder =>
{
appBuilder.AlwaysUseThisMiddleware(); // Duplicated
appBuilder.SometimesUseThisOtherOne;
)
简答:
是的。它将按您的预期工作。
其实我们在Use()
一系列中间件的时候,就是在注册一系列的中间件,处理请求的时候会依次调用这些中间件。
MapWhen()
方法只不过是辅助方法 that invokes the Use()
. What MapWhen(predicate,configFn)
does is to registering something that runs as below :
if (predicate(context)){
await branch(context);
} else {
await _next(context);
}
因此,当我们调用 MapWhen()
时,我们正在注册另一个分支处理的中间件。
例如:
app.UseMiddleware<AlwaysUseThisMiddleware>();
app.MapWhen(ctx=>ctx.Request.Query["a"]=="1", appBuilder =>{
appBuilder.UseMiddleware<SometimesUseThisOne>();
});
app.MapWhen(ctx=>ctx.Request.Query["b"]=="1", appBuilder =>{
appBuilder.UseMiddleware<SometimesUseThisOtherOne>();
})
// ...
基本上,此代码按以下方式运行:
call `AlwaysUseThisMiddleware`;
////////////////////////////////////
if (ctx.Request.Query["a"]=="1"){
call SometimesUseThisOne ;
} else {
//------------------------------------------
if (ctx.Request.Query["b"]=="1"){
call SometimesUseThisOtherOne ;
} else {
//##################################################
await _next(context); // call other middlewares ...
//##################################################
}
//-----------------------------------------
}
////////////////////////////////////
或者如果你喜欢也可以重写如下:
call `AlwaysUseThisMiddleware` middleware
if(ctx.Request.Query["a"]=="1") // go to branch 1
call `SometimesUseThisOne` middleware
else if (ctx.Request.Query["b"]=="1") // go to branch 2
call `SometimesUseThisOtherOne` middleware
else :
...
注意这里的分支被翻译成 else if
而不是 if
。并且中间件 AlwaysUseThisMiddleware
总是在 branch1 & branch2 之前被调用。