如何在ASP.NET Core中解析ConfigureServices中的实例

时间:2015-08-06 19:11:57

标签: c# asp.net-core inversion-of-control asp.net-core-mvc

是否可以从Startup中的IOptions<AppSettings>方法解析ConfigureServices的实例?通常情况下,您可以使用IServiceProvider初始化实例,但在注册服务时,您暂时没有实例。

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<AppSettings>(
        configuration.GetConfigurationSection(nameof(AppSettings)));

    // How can I resolve IOptions<AppSettings> here?
}

6 个答案:

答案 0 :(得分:89)

您可以使用BuildServiceProvider()上的IServiceCollection方法构建服务提供商:

public void ConfigureService(IServiceCollection services)
{
    // Configure the services
    services.AddTransient<IFooService, FooServiceImpl>();
    services.Configure<AppSettings>(configuration.GetSection(nameof(AppSettings)));

    // Build an intermediate service provider
    var sp = services.BuildServiceProvider();

    // Resolve the services from the service provider
    var fooService = sp.GetService<IFooService>();
    var options = sp.GetService<IOptions<AppSettings>>();
}

您需要Microsoft.Extensions.DependencyInjection包。

如果您只需要绑定ConfigureServices中的某些选项,您还可以使用Bind方法:

var appSettings = new AppSettings();
configuration.GetSection(nameof(AppSettings)).Bind(appSettings);

此功能可通过Microsoft.Extensions.Configuration.Binder包获得。

答案 1 :(得分:13)

在所有版本的ASP.NET Core中,最简单,最正确的方法是实现IConfigureOptions<TOptions>接口。尽管自.NET Core 1.0开始就存在这种情况,但似乎很少有人了解how it makes things Just Work™

作为一个示例,您想添加一个依赖于应用程序其他服务之一的自定义模型验证器。最初似乎是不可能的-无法解决IMyServiceDependency,因为您无权访问IServiceProvider

public class MyModelValidatorProvider : IModelValidatorProvider
{
    public MyModelValidatorProvider(IMyServiceDependency dependency)
    {
        ...
    }
}

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers(options =>
    {
        options.ModelValidatorProviders.Add(new MyModelValidatorProvider(??????));
    });
}

但是IConfigureOptions<TOptions>的“魔力”变得如此简单:

public class ConfigureMvcOptions : IConfigureOptions<MvcOptions>
{
    private IMyServiceDependency _dependency;

    public MyMvcOptions(IMyServiceDependency dependency)
        => _dependency = dependency;

    public void Configure(MvcOptions options)
        => options.ModelValidatorProviders.Add(new MyModelValidatorProvider(_dependency));
}

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers();

    ...

    // or scoped, or transient, as necessary for your service
    services.AddSingleton<IConfigureOptions<MvcOptions>, ConfigureMvcOptions>();
}

基本上,您在Add***(***Options)的{​​{1}}委托中所做的任何设置现在都将移至您的ConfigureServices类的IConfigureOptions<TOptions>方法中。然后,您可以使用注册其他服务的相同方式注册选项,然后离开!

有关更多详细信息以及有关其如何在后台工作的信息,I refer you to the always-excellent Andrew Lock

答案 2 :(得分:3)

实例化依赖于其他服务的类的最佳方法是使用 Add XXX 重载,该重载为您提供 IServiceProvider 。这样,您无需实例化中间服务提供商。

以下示例显示了如何在 AddSingleton / AddTransient 方法中使用此重载。

        services.AddSingleton(serviceProvider =>
        {
            var options = serviceProvider.GetService<IOptions<AppSettings>>();
            var foo = new Foo(options);
            return foo ;
        });


        services.AddTransient(serviceProvider =>
        {
            var options = serviceProvider.GetService<IOptions<AppSettings>>();
            var bar = new Bar(options);
            return bar;
        });

答案 3 :(得分:1)

你在寻找像下面这样的东西吗?您可以在代码中查看我的评论:

// this call would new-up `AppSettings` type
services.Configure<AppSettings>(appSettings =>
{
    // bind the newed-up type with the data from the configuration section
    ConfigurationBinder.Bind(appSettings, Configuration.GetConfigurationSection(nameof(AppSettings)));

    // modify these settings if you want to
});

// your updated app settings should be available through DI now

答案 4 :(得分:-1)

想帮助其他看起来一样但也使用Autofac的人。

如果要获取ILifetimeScope(即当前作用域的容器),则需要在app.ApplicationServices.GetAutofacRoot()中调用Configure(IApplicationBuilder app)方法,这将返回ILifetimeScope实例,可用于解析服务

public void Configure(IApplicationBuilder app)
    {
        //app middleware registrations 
        //...
        //

        ILifetimeScope autofacRoot = app.ApplicationServices.GetAutofacRoot();
        var repository = autofacRoot.Resolve<IRepository>();
    }

答案 5 :(得分:-1)

在 MVC Core 3.1 或 .Net 5 中,您可以通过两行将 IOptions 传递给 Startup.cs 中的服务:

首先注册您的 IOptions 设置:

services.Configure<MySettings>(Configuration.GetSection("MySection"));

然后是您的服务注册,传入 IOptions

services.AddSingleton<IMyService, MyService>(x => new MyService(x.GetService<IOptions<MySettings>>()));