在 BackgroundService 中对多个 类 使用 DI
Using DI for Multiple Classes In BackgroundService
我正在构建一个文件夹监控服务来显示多个文件夹中的文件,这些文件已经在文件夹中放置了一个多小时。我在将 appsettings.json
值注入多个 类.
时遇到问题
appsettings.json 文件
{
"FolderLocations": {
"InsertLocation": "C:\Insert\",
"ReplaceLocation": "C:\Replace\",
"DeleteLocation": "C:\Delete\"
},
"EmailSettings": {
"SmtpServer": "host",
"SmtpPort": 25
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.Hosting.Lifetime": "Information"
}
}
}
AppSettingsConfiguration,cs
public class AppSettingsConfiguration
{
public string InsertLocation { get; set; }
public string ReplaceLocation { get; set; }
public string DeleteLocation { get; set; }
public string SmtpServer { get; set; }
public int SmtpPort { get; set; }
}
Program.cs
IHost host = Host.CreateDefaultBuilder(args)
.UseWindowsService(options =>
{
options.ServiceName = "Folder Monitor";
})
.ConfigureServices((hostContext, services) => {
services.Configure<AppSettingsConfiguration>(hostContext.Configuration.GetSection("FolderLocations"));
services.AddSingleton<IFolderMonitorManager, FolderMonitorManager>();
services.Configure<AppSettingsConfiguration>(hostContext.Configuration.GetSection("EmailSettings"));
services.AddLogging();
services.AddSingleton<IEmail, Email>();
services.AddHostedService<WindowsBackgroundService>();
})
.Build();
await host.RunAsync();
WindowsBackgroundService.cs
public class WindowsBackgroundService : BackgroundService
{
private readonly IFolderMonitorManager _folderMonitorManager;
private readonly ILogger<WindowsBackgroundService> _logger;
public WindowsBackgroundService(
IFolderMonitorManager folderMonitorManager,
ILogger<WindowsBackgroundService> logger) =>
(_folderMonitorManager, _logger) = (folderMonitorManager, logger);
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
_logger.LogWarning($"===== Starting Folder Monitor @ {DateTime.Now:MM/dd/yy HH:mm:ss} =====");
await _folderMonitorManager.StartMonitoringProcess();
await Task.Delay(TimeSpan.FromMinutes(1), stoppingToken);
}
}
}
FolderMonitorManager.cs
internal class FolderMonitorManager : IFolderMonitorManager
{
private readonly AppSettingsConfiguration _config;
private readonly ILogger<FolderMonitorManager> _logger;
private List<string> _folders;
private List<string> _files;
private List<string> _filesFoundOverHour;
private readonly IEmail _email;
public FolderMonitorManager(IOptions<AppSettingsConfiguration> config, ILogger<FolderMonitorManager> logger)
{
_config = config.Value;
_logger = logger;
_filesFoundOverHour = new List<string>();
}
public async Task StartMonitoringProcess()
{
try
{
await CheckFoldersFromAppSettings();
}
catch (Exception)
{
throw;
}
}
private async Task CheckFoldersFromAppSettings()
{
//File Locations from appsettings.json
_folders = new(){
_config.InsertLocation,
_config.DeleteLocation,
_config.ReplaceLocation
};
try
{
foreach (var folder in _folders)
{
_files = FolderLocations.GetFilesInLocation(folder);
foreach (var file in FolderLocations.GetFileLastWriteTime(_files))
{
_filesFoundOverHour.Add(file);
}
}
}
catch (Exception)
{
throw;
}
_logger.LogWarning($"===== Finished Folder Monitor @ {DateTime.Now:MM/dd/yy HH:mm:ss} =====");
Console.WriteLine(_filesFoundOverHour.Count);
SendEmail();
}
public void SendEmail()
{
Console.WriteLine("Email Send hit");
_email.Send(); //Getting Null Exception here
}
}
Email.cs
public class Email : IEmail
{
private readonly AppSettingsConfiguration _config;
private readonly ILogger<Email> _logger;
private string FromEmailAddress = "NOREPLY@domain.com";
public Email()
{
}
public Email(IOptions<AppSettingsConfiguration> config, ILogger<Email> logger)
{
_config = config.Value;
_logger = logger;
}
public async Task Send()
{
// create email message
var email = new MimeMessage();
email.From.Add(MailboxAddress.Parse(FromEmailAddress));
email.To.Add(MailboxAddress.Parse("user@domain.com"));
email.Subject = "Test Email Subject";
email.Body = new TextPart(TextFormat.Html) { Text = "<h1>Example HTML Message Body</h1>" };
using (var client = new SmtpClient())
{
//Here's where I need to be able to read the appsettings.json
client.Connect(_config.SmtpServer, _config.SmtpPort, false);
// Note: only needed if the SMTP server requires authentication
//client.Authenticate("joey", "password");
client.Send(email);
client.Disconnect(true);
}
}
}
在 Email.Send()
的 using
语句中,我需要能够读取 SmtpServer
和 SmtpPort
值。
在 FolderMonitorManager.cs
文件中,我得到 Null Exception
和 _email.Send()
。我明白为什么。有没有办法能够读取所有 类 中的 AppSettingsConfiguration.cs
值?
由于JSON没有映射到对象模型,所以需要在配置选项时手动绑定
IHost host = Host.CreateDefaultBuilder(args)
.UseWindowsService(options =>
{
options.ServiceName = "Folder Monitor";
})
.ConfigureServices((hostContext, services) => {
//Configure settings
services.Configure<AppSettingsConfiguration>(options => {
hostContext.Configuration.GetSection("FolderLocations").Bind(options);
hostContext.Configuration.GetSection("EmailSettings").Bind(options);
});
services.AddSingleton<IFolderMonitorManager, FolderMonitorManager>();
services.AddLogging();
services.AddSingleton<IEmail, Email>();
services.AddHostedService<WindowsBackgroundService>();
})
.Build();
参考:Bind hierarchical configuration
FolderMonitorManager
也不会为 _email
赋值,因为它没有被注入构造函数
public FolderMonitorManager(IOptions<AppSettingsConfiguration> config, ILogger<FolderMonitorManager> logger, IEmail email)
{
_config = config.Value;
_logger = logger;
_filesFoundOverHour = new List<string>();
_email = email; //<--
}
我正在构建一个文件夹监控服务来显示多个文件夹中的文件,这些文件已经在文件夹中放置了一个多小时。我在将 appsettings.json
值注入多个 类.
appsettings.json 文件
{
"FolderLocations": {
"InsertLocation": "C:\Insert\",
"ReplaceLocation": "C:\Replace\",
"DeleteLocation": "C:\Delete\"
},
"EmailSettings": {
"SmtpServer": "host",
"SmtpPort": 25
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.Hosting.Lifetime": "Information"
}
}
}
AppSettingsConfiguration,cs
public class AppSettingsConfiguration
{
public string InsertLocation { get; set; }
public string ReplaceLocation { get; set; }
public string DeleteLocation { get; set; }
public string SmtpServer { get; set; }
public int SmtpPort { get; set; }
}
Program.cs
IHost host = Host.CreateDefaultBuilder(args)
.UseWindowsService(options =>
{
options.ServiceName = "Folder Monitor";
})
.ConfigureServices((hostContext, services) => {
services.Configure<AppSettingsConfiguration>(hostContext.Configuration.GetSection("FolderLocations"));
services.AddSingleton<IFolderMonitorManager, FolderMonitorManager>();
services.Configure<AppSettingsConfiguration>(hostContext.Configuration.GetSection("EmailSettings"));
services.AddLogging();
services.AddSingleton<IEmail, Email>();
services.AddHostedService<WindowsBackgroundService>();
})
.Build();
await host.RunAsync();
WindowsBackgroundService.cs
public class WindowsBackgroundService : BackgroundService
{
private readonly IFolderMonitorManager _folderMonitorManager;
private readonly ILogger<WindowsBackgroundService> _logger;
public WindowsBackgroundService(
IFolderMonitorManager folderMonitorManager,
ILogger<WindowsBackgroundService> logger) =>
(_folderMonitorManager, _logger) = (folderMonitorManager, logger);
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
_logger.LogWarning($"===== Starting Folder Monitor @ {DateTime.Now:MM/dd/yy HH:mm:ss} =====");
await _folderMonitorManager.StartMonitoringProcess();
await Task.Delay(TimeSpan.FromMinutes(1), stoppingToken);
}
}
}
FolderMonitorManager.cs
internal class FolderMonitorManager : IFolderMonitorManager
{
private readonly AppSettingsConfiguration _config;
private readonly ILogger<FolderMonitorManager> _logger;
private List<string> _folders;
private List<string> _files;
private List<string> _filesFoundOverHour;
private readonly IEmail _email;
public FolderMonitorManager(IOptions<AppSettingsConfiguration> config, ILogger<FolderMonitorManager> logger)
{
_config = config.Value;
_logger = logger;
_filesFoundOverHour = new List<string>();
}
public async Task StartMonitoringProcess()
{
try
{
await CheckFoldersFromAppSettings();
}
catch (Exception)
{
throw;
}
}
private async Task CheckFoldersFromAppSettings()
{
//File Locations from appsettings.json
_folders = new(){
_config.InsertLocation,
_config.DeleteLocation,
_config.ReplaceLocation
};
try
{
foreach (var folder in _folders)
{
_files = FolderLocations.GetFilesInLocation(folder);
foreach (var file in FolderLocations.GetFileLastWriteTime(_files))
{
_filesFoundOverHour.Add(file);
}
}
}
catch (Exception)
{
throw;
}
_logger.LogWarning($"===== Finished Folder Monitor @ {DateTime.Now:MM/dd/yy HH:mm:ss} =====");
Console.WriteLine(_filesFoundOverHour.Count);
SendEmail();
}
public void SendEmail()
{
Console.WriteLine("Email Send hit");
_email.Send(); //Getting Null Exception here
}
}
Email.cs
public class Email : IEmail
{
private readonly AppSettingsConfiguration _config;
private readonly ILogger<Email> _logger;
private string FromEmailAddress = "NOREPLY@domain.com";
public Email()
{
}
public Email(IOptions<AppSettingsConfiguration> config, ILogger<Email> logger)
{
_config = config.Value;
_logger = logger;
}
public async Task Send()
{
// create email message
var email = new MimeMessage();
email.From.Add(MailboxAddress.Parse(FromEmailAddress));
email.To.Add(MailboxAddress.Parse("user@domain.com"));
email.Subject = "Test Email Subject";
email.Body = new TextPart(TextFormat.Html) { Text = "<h1>Example HTML Message Body</h1>" };
using (var client = new SmtpClient())
{
//Here's where I need to be able to read the appsettings.json
client.Connect(_config.SmtpServer, _config.SmtpPort, false);
// Note: only needed if the SMTP server requires authentication
//client.Authenticate("joey", "password");
client.Send(email);
client.Disconnect(true);
}
}
}
在 Email.Send()
的 using
语句中,我需要能够读取 SmtpServer
和 SmtpPort
值。
在 FolderMonitorManager.cs
文件中,我得到 Null Exception
和 _email.Send()
。我明白为什么。有没有办法能够读取所有 类 中的 AppSettingsConfiguration.cs
值?
由于JSON没有映射到对象模型,所以需要在配置选项时手动绑定
IHost host = Host.CreateDefaultBuilder(args)
.UseWindowsService(options =>
{
options.ServiceName = "Folder Monitor";
})
.ConfigureServices((hostContext, services) => {
//Configure settings
services.Configure<AppSettingsConfiguration>(options => {
hostContext.Configuration.GetSection("FolderLocations").Bind(options);
hostContext.Configuration.GetSection("EmailSettings").Bind(options);
});
services.AddSingleton<IFolderMonitorManager, FolderMonitorManager>();
services.AddLogging();
services.AddSingleton<IEmail, Email>();
services.AddHostedService<WindowsBackgroundService>();
})
.Build();
参考:Bind hierarchical configuration
FolderMonitorManager
也不会为 _email
赋值,因为它没有被注入构造函数
public FolderMonitorManager(IOptions<AppSettingsConfiguration> config, ILogger<FolderMonitorManager> logger, IEmail email)
{
_config = config.Value;
_logger = logger;
_filesFoundOverHour = new List<string>();
_email = email; //<--
}