是否可以从Startup中的IOptions<AppSettings>
方法解析ConfigureServices
的实例?通常情况下,您可以使用IServiceProvider
初始化实例,但在注册服务时,您暂时没有实例。
public void ConfigureServices(IServiceCollection services)
{
services.Configure<AppSettings>(
configuration.GetConfigurationSection(nameof(AppSettings)));
// How can I resolve IOptions<AppSettings> here?
}
答案 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>>()));