我正在学习.net core提供的依赖注入。 到目前为止,我已经知道以下5种方法。
// 0
sc.AddSingleton(configuration);
//1
sc.Configure<ServiceOption>(_ => configuration.GetSection(nameof(ServiceOption)).Bind(_));
//2
sc.Configure<ServiceOption>(configuration.GetSection(nameof(ServiceOption)));
//3
sc.AddOptions<ServiceOption>()
.Bind(configuration.GetSection(nameof(ServiceOption)));
//4
sc.Configure<ServiceOption>(_ => _.ID = "from hard code");
最后一个(#4)对我而言并不那么有趣,所以请忽略它。 我想知道,我们什么时候需要使用其余的每个?
这是源代码。
appsettings.json
文件:
{
"ServiceOption": {
"ID": "from appsettings.json"
}
}
代码:
interface IService
{
void Do();
}
class Service : IService
{
readonly ServiceOption option;
readonly IConfigurationRoot configuration;
public Service(IOptionsMonitor<ServiceOption> option)
{
this.option = option.CurrentValue;
}
public Service(IConfigurationRoot configuration)
{
this.configuration = configuration;
}
public void Do(){}
}
class ServiceOption
{
public string ID { get; set; }
}
class Program
{
private static readonly IConfigurationRoot configuration;
static Program()
{
configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: true)
.Build();
}
static void Main()
{
using (ServiceProvider sp = RegisterServices())
{
sp.GetRequiredService<IService>().Do();
}
}
static ServiceProvider RegisterServices()
{
ServiceCollection sc = new ServiceCollection();
sc.AddTransient<IService, Service>();
int selector = 0;
switch (selector)
{
case 0:
sc.AddSingleton(configuration);
break;
case 1:
sc.Configure<ServiceOption>(_ => configuration.GetSection(nameof(ServiceOption)).Bind(_));
break;
case 2:
sc.Configure<ServiceOption>(configuration.GetSection(nameof(ServiceOption)));
break;
case 3:
sc.AddOptions<ServiceOption>()
.Bind(configuration.GetSection(nameof(ServiceOption)));
break;
default:
sc.Configure<ServiceOption>(_ => _.ID = "from hard code");
break;
}
return sc.BuildServiceProvider();
}
}
答案 0 :(得分:2)
sc.AddSingleton(configuration);
这将注册该类的单个实例。当您不希望使用代码必须了解Microsoft.Extensions.Options
时,这很有用。另一个常见的情况是您不打算使用“选项”模式提供的功能。
sc.Configure<ServiceOption>(_ => configuration.GetSection(nameof(ServiceOption)).Bind(_));
这使您可以使用功能配置选项。但是,由于您只是绑定到已经构建的Configuration,所以使用的语法很奇怪。
sc.Configure<ServiceOption>(configuration.GetSection(nameof(ServiceOption)));
与上面的操作相同,但是直接绑定到Configuration实例。
sc.AddOptions<ServiceOption>().Bind(configuration.GetSection(nameof(ServiceOption)));
这只是给您一个OptionBuilder<T>
,您可以用它在一次流畅的通话中调用Bind
,Configure
和PostConfigure
。
答案 1 :(得分:1)
此答案是要添加排除的其他选项
//bind to an object graph using `ConfigurationBinder.Get<T>`
ServiceOption setting = configuration.GetSection(nameof(ServiceOption)).Get<ServiceOption>();
//adding that to the service collection as needed
sc.AddSingleton(setting);
ConfigurationBinder.Get<T>
绑定并返回指定的类型。Get<T>
比使用Bind
更方便。
在上面的选项中,可以将其显式注入到依赖项中
public Service(ServiceOption option) {
this.option = option;
}
如果您不想将您的从属代码直接耦合到框架相关的关注点,则其推理类似于已经提供的答案。
引用Configuration in ASP.NET Core: Bind to an object graph
理想情况下,如果您不希望应用程序代码对框架抽象产生不必要的依赖,则不希望注入IConfiguration
或IOptions
。