为什么 ASP.NET Core 中的中间件需要特定的语义,而不是接口?

Why middleware in ASP.NET Core requires specific semantics, but not an interface?

众所周知,ASP.NET Core 中方法 Configure (class Startup) 的 IApplicationBuilder 需要特定语义(方法 'Invoke' 的输入参数为 HttpContext 类型,任务为 return 值)。但是为什么它没有作为接口实现呢?我可以这样写:

public class FakeMiddleware
{

}

并注册:

    app.UseMiddleware<FakeMiddleware>();

我们会得到一个运行时错误。当然,这是一件很简单的事情,很容易被发现和修复,但是实现起来很粗糙,没有界面?

Invoke 方法很灵活,您可以要求额外的参数。 ASP.NET 将使用应用程序的服务配置注入附加参数。

public async Task Invoke(HttpContext ctx, 
                         IHostingEnvironment host,
                         ISomethingElse service)
{
    // ...
}

C# 接口定义无法很好地提供这种灵活性。

Since AspNetCore2.0你可以设置实现接口IMiddleware的中间件。

public class InterfaceMiddleware : IMiddleware
{
    private InterfaceMiddlewareOptions _opts;

    public InterfaceMiddleware(IOptions<InterfaceMiddlewareOptions> opts)
    {
        _opts = opts.Value;
    }

    public async Task InvokeAsync(HttpContext context, RequestDelegate next)
    {
        await context.Response.WriteAsync(_opts.Message);
    }
}

除了app.UseMiddleware<InterfaceMiddleware>()。您需要在 DI 中注册您的中间件(不需要单例生命周期)。

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<InterfaceMiddlewareOptions>(opts =>
    {
        opts.Message = "IMiddleware interface is implemented";
    });

    services.AddSingleton<InterfaceMiddleware>();
}