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

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc(options =>
    {
        options.MaxModelValidationErrors = 100;
    });
}

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

最佳答案

如果查看sourceAddMvc,您会发现它没有为您创建MvcOptions的实例:

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

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

    return builder;
}

相反,它使用 IServiceCollection.Configure 挂接到更通用的Options pattern in ASP.NET Core中。在幕后,这将 IConfigureOptions<MvcOptions> 实例添加到“依赖项注入(inject)”容器中,最终将在稍后的某个时间运行您的委托(delegate)。

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

所有这些都提供了一定的灵活性。您可以建立代表以预定顺序配置MvcOptions的代表管道,每个配置步骤可能来自其他项目,等等。甚至可以在调用services.Configure<MvcOptions>(...)等之前拥有自己的AddMvc调用。

将MVC服务添加到DI时,可以使用AddMvcAddMvcCore。在内部,AddMvc调用AddMvcCore,因此我们可以将AddMvc视为AddMvcCore的某种扩展。
AddMvcCore adds its own configuration,使用Options pattern in ASP.NET CoreMvcOptions不会创建AddMvcCore本身的实例,而是将一组 IConfigureOptions<MvcOptions> IPostConfigureOptions<MvcOptions> 添加到Dependency Injection容器中。

这两个接口(interface)用于组装一种形式的管道,其中所有IConfigureOptions<MvcOptions>首先运行(按它们添加到DI的顺序),所有IPostConfigureOptions<MvcOptions>随后运行(再次按顺序)。这允许AddMvcCore提供一些默认值(使用IConfigureOptions<MvcOptions>),并且还提供一旦应用了所有其他配置(使用MvcOptions)就可以对IPostConfigureOptions<MvcOptions>进行更改的功能。

当您调用AddMvc并提供委托(delegate)时,该委托(delegate)将在IConfigureOptions<MvcOptions>添加的AddMvcCore之后运行,这提供了在应用程序中覆盖这些默认值的能力。

关于c# - 为什么AddMvc需要Action <MvcOptions>而不是MvcOptions?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/54147660/

10-10 11:10