为什么AddMvc需要Action <MvcOptions>而不是MvcOptions?

Lor*_*eno 4 c# asp.net-core

我正在学习ASP.NET Core,我看到注册MVC服务看起来像这样:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc(options =>
    {
        options.MaxModelValidationErrors = 100;
    });
}
Run Code Online (Sandbox Code Playgroud)

我的问题是,为什么该AddMvc方法需要以Action<MvcOptions>?的形式选择?为什么我不能只创建一个实例MvcOptions并将其传递给函数?

Kir*_*kin 13

如果你看一下AddMvc,你会发现它创建的实例MvcOptions为您提供:

public static IMvcBuilder AddMvc(this IServiceCollection services, Action<MvcOptions> setupAction)
{
    ...

    var builder = services.AddMvc();
    builder.Services.Configure(setupAction);

    return builder;
}
Run Code Online (Sandbox Code Playgroud)

相反,它用于IServiceCollection.Configure挂钩ASP.NET Core中更通用的Options模式.在幕后,这会IConfigureOptions<MvcOptions>向Dependency Injection容器添加一个实例,该容器将在稍后的某个时间点运行您的委托.

可以添加多个实例IConfigureOptions<MvcOptions>,这些实例将按注册顺序运行.还有IServiceCollection.PostConfigure一些注册实例IPostConfigureOptions<MvcOptions>- 这些实例将所有IConfigureOptions<MvcOptions>实例(docs)之后运行.

这一切都提供了一些灵活性 您可以设置代表一个管道用于配置MvcOptions一组订单,其中每一个配置步骤可能来自其他项目等你甚至可以有自己的呼叫services.Configure<MvcOptions>(...)你的电话之前AddMvc,等等.


将MVC服务添加到DI时,可以使用AddMvc或者AddMvcCore.在内部,AddMvc通话AddMvcCore,所以我们可以将其AddMvc视为某种延伸AddMvcCore.

AddMvcCore 使用ASP.NET Core中Options模式添加自己的配置.而不是创建MvcOptions自己的实例,AddMvcCore添加一组IConfigureOptions<MvcOptions>IPostConfigureOptions<MvcOptions>依赖注入容器.

这两个接口用于组装管道形式,其中所有接口都IConfigureOptions<MvcOptions>先运行(按照它们添加到DI的顺序),然​​后全部IPostConfigureOptions<MvcOptions>运行第二个(再次按顺序运行).这允许AddMvcCore提供一些默认值(使用IConfigureOptions<MvcOptions>),并且还提供在MvcOptions应用所有其他配置(使用IPostConfigureOptions<MvcOptions>)后进行更改的功能.

当你打电话AddMvc,并提供一个代表说,代表将运行后,IConfigureOptions<MvcOptions>被添加的AddMvcCore,它提供给你的应用程序中覆盖这些默认值的能力.