C# 通过IOOptions将辅助服务中的依赖项注入到控制器以外的类
我知道这是一个重复的问题,我看了一遍答案,不知道这里发生了什么。在这个问题中,我们需要将值从C# 通过IOOptions将辅助服务中的依赖项注入到控制器以外的类,c#,dependency-injection,asp.net-core-3.1,C#,Dependency Injection,Asp.net Core 3.1,我知道这是一个重复的问题,我看了一遍答案,不知道这里发生了什么。在这个问题中,我们需要将值从appsettings.json传输到另一个类,而不是这里的ControllersServiceSettings.cs 这是一个类似“hello world”的示例程序,这里我们需要将值从appsettings.json传输到插件 这是文件夹体系结构 appsettings.json "Application": { "TimerInterval": 10
appsettings.json
传输到另一个类,而不是这里的ControllersServiceSettings.cs
这是一个类似“hello world”的示例程序,这里我们需要将值从appsettings.json
传输到插件
这是文件夹体系结构appsettings.json
"Application": {
"TimerInterval": 10000,
"LogLevel": "Debug"
}
我在类库中基于此应用程序设置创建了一个类-
ApplicationSettings.cs
public class ApplicationSettings
{
public int TimerInterval { get; set; }
public string LogLevel { get; set; }
}
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseWindowsService()
.ConfigureServices((hostContext, services) =>
{
services.AddSingleton<IConfiguration>(hostContext.Configuration);
// Service Settings Injected here
services.AddOptions<ServiceSettings>();
services.AddHostedService<Worker>();
services.Configure<ApplicationSettings>(hostContext.Configuration.GetSection("Application"));
// for configure application
});
}
public class ServiceSettings
{
private readonly IOptions<ApplicationSettings> _appSettings;
public ServiceSettings(IOptions<ApplicationSettings> appSettings)
{
_appSettings = appSettings;
}
public int TimerInterval { get; set; }
public string LogLevel { get; set; }
public void Load()
{
// Error is shown here
try { TimerInterval = Convert.ToInt32(_appSettings.Value.TimerInterval); }
catch { TimerInterval = 60; }
try
// Here too
{ LogLevel = Convert.ToString(_appSettings.Value.LogLevel).ToLower(); }
catch { LogLevel = "info"; }
}
}
我尝试通过最后一行代码从appsettings推送数据
services.Configure<ApplicationSettings>(hostContext.Configuration.GetSection("Application"));
下面提供了接收空值的服务设置值
ServiceSettings.cs
public class ApplicationSettings
{
public int TimerInterval { get; set; }
public string LogLevel { get; set; }
}
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseWindowsService()
.ConfigureServices((hostContext, services) =>
{
services.AddSingleton<IConfiguration>(hostContext.Configuration);
// Service Settings Injected here
services.AddOptions<ServiceSettings>();
services.AddHostedService<Worker>();
services.Configure<ApplicationSettings>(hostContext.Configuration.GetSection("Application"));
// for configure application
});
}
public class ServiceSettings
{
private readonly IOptions<ApplicationSettings> _appSettings;
public ServiceSettings(IOptions<ApplicationSettings> appSettings)
{
_appSettings = appSettings;
}
public int TimerInterval { get; set; }
public string LogLevel { get; set; }
public void Load()
{
// Error is shown here
try { TimerInterval = Convert.ToInt32(_appSettings.Value.TimerInterval); }
catch { TimerInterval = 60; }
try
// Here too
{ LogLevel = Convert.ToString(_appSettings.Value.LogLevel).ToLower(); }
catch { LogLevel = "info"; }
}
}
公共类服务设置
{
私有只读IOPS\u应用设置;
公共服务设置(IOPS应用设置)
{
_appSettings=appSettings;
}
公共int TimerInterval{get;set;}
公共字符串日志级别{get;set;}
公共空荷载()
{
//错误显示在这里
请尝试{TimerInterval=Convert.ToInt32(_appSettings.Value.TimerInterval);}
catch{TimerInterval=60;}
尝试
//这里也是
{LogLevel=Convert.ToString(_appSettings.Value.LogLevel).ToLower();}
catch{LogLevel=“info”;}
}
}
我对工人服务很陌生,我在这里错过了什么?请为我提供资源,谢谢大家。这似乎是一个设计问题 首先,让我们修复组合根。避免注入
i配置
。它可以被看作是一种代码气味,因为i配置
在理想情况下应用于启动
public class Program {
public static void Main(string[] args) {
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseWindowsService()
.ConfigureServices((hostContext, services) => {
IConfiguration config = hostContext.Configuration;
// parse settings
ApplicationSettings appSettings = config
.GetSection("Application").Get<ApplicationSettings>();
//set defaults.
if(appSettings.TimerInterval == 0)
appSettings.TimerInterval = 60;
if(string.IsNullOrWhiteSpace(appSettings.LogLevel))
appSettings.LogLevel = "Debug";
services.AddSingleton(appSettings); //<-- register settings run-time data
services.AddHostedService<Worker>();
});
}
这似乎是一个设计问题 首先,让我们修复组合根。避免注入
i配置
。它可以被看作是一种代码气味,因为i配置
在理想情况下应用于启动
public class Program {
public static void Main(string[] args) {
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseWindowsService()
.ConfigureServices((hostContext, services) => {
IConfiguration config = hostContext.Configuration;
// parse settings
ApplicationSettings appSettings = config
.GetSection("Application").Get<ApplicationSettings>();
//set defaults.
if(appSettings.TimerInterval == 0)
appSettings.TimerInterval = 60;
if(string.IsNullOrWhiteSpace(appSettings.LogLevel))
appSettings.LogLevel = "Debug";
services.AddSingleton(appSettings); //<-- register settings run-time data
services.AddHostedService<Worker>();
});
}
您始终必须从服务集合中获取实例。通常通过在类构造函数中注入它们来实现这一点
// WRONG
// Worker.cs
_settings = new ServiceSettings();
ServiceSettings
和ApplicationSettings
是相同的。如果您需要服务注入中的应用程序设置IOptions
,仅此而已。如果需要单独的设置类,请将它们作为IOption
提供
最后,它可能看起来是这样的:
public class Worker {
private readonly ApplicationSettings _settings;
private readonly ILogger<Worker> _logger;
public Worker(IOptions<ApplicationSettings> settingsAccessor, ILogger<Worker> logger) {
_settings = settingsAccessor.Value;
_logger = logger;
}
public override Task StartAsync(CancellationToken cancellationToken) {
Console.WriteLine("Start Asynch Method");
_logger.LogInformation("Settings: {setting}", _settings.TimerInterval);
return base.StartAsync(cancellationToken);
}
}
公共类工作者{
专用只读应用程序设置\u设置;
专用只读ILogger\u记录器;
公共工作者(IOptions设置访问器、ILogger记录器){
_设置=设置Accessor.Value;
_记录器=记录器;
}
公共覆盖任务StartAsync(CancellationToken CancellationToken){
WriteLine(“启动异步方法”);
_logger.LogInformation(“设置:{setting}”,_Settings.TimerInterval);
返回base.StartAsync(cancellationToken);
}
}
请注意,reading settingsAccessor.Value是框架真正尝试访问配置的地方,因此这里我们应该考虑错误情况(如果之前未验证)。您必须始终从服务集合中获取实例。通常通过在类构造函数中注入它们来实现这一点
// WRONG
// Worker.cs
_settings = new ServiceSettings();
ServiceSettings
和ApplicationSettings
是相同的。如果您需要服务注入中的应用程序设置IOptions
,仅此而已。如果需要单独的设置类,请将它们作为IOption
提供
最后,它可能看起来是这样的:
public class Worker {
private readonly ApplicationSettings _settings;
private readonly ILogger<Worker> _logger;
public Worker(IOptions<ApplicationSettings> settingsAccessor, ILogger<Worker> logger) {
_settings = settingsAccessor.Value;
_logger = logger;
}
public override Task StartAsync(CancellationToken cancellationToken) {
Console.WriteLine("Start Asynch Method");
_logger.LogInformation("Settings: {setting}", _settings.TimerInterval);
return base.StartAsync(cancellationToken);
}
}
公共类工作者{
专用只读应用程序设置\u设置;
专用只读ILogger\u记录器;
公共工作者(IOptions设置访问器、ILogger记录器){
_设置=设置Accessor.Value;
_记录器=记录器;
}
公共覆盖任务StartAsync(CancellationToken CancellationToken){
WriteLine(“启动异步方法”);
_logger.LogInformation(“设置:{setting}”,_Settings.TimerInterval);
返回base.StartAsync(cancellationToken);
}
}
请注意,reading settingsAccessor.Value是框架真正尝试访问配置的地方,因此在这里我们应该考虑错误条件(如果之前未验证)。您介意检查一下吗?你介意也检查一下吗?你介意也检查一下吗?你介意也检查一下吗?