我有一个选项类,如下所示
public class EmailOptions
{
public EmailOptions(IEmailConfiguration account) {
this.Configuration = account;
}
public string DefaultFromAddress { get; set; }
public string DefaultFromDisplayName { get; set; }
public IEmailConfiguration Configuration { get; }
}
IEmailConfiguration接口在那里,因为在某些情况下我可以有一个Smtp库,所以我需要一个基于Smtp的配置,而在其他一些情况下,我可以使用其他需要不同配置的服务。例:
public class ApiKeyConfiguration : IEmailConfiguration
{
public ApiKeyConfiguration() {
}
public string AccountName { get; set; }
public string AccountKey { get; set; }
}
要么
public class SmtpConfiguration : IEmailConfiguration
{
public SmtpConfiguration() {
}
public string Host { get; set; }
public string Port { get; set; }
public string Username { get; set; }
public string Password { get; set; }
public string Domain { get; set; }
public bool EnableSsl { get; set; }
public bool UseDefaultCredentials { get; set; }
}
我确信我正在注册正确的实现
services.AddTransient<IEmailConfiguration, ApiKeyConfiguration>();
但是,当我尝试将IOption <>注入控制器时,我收到以下错误:
[13:56:26 ERR]发生了未处理的异常:无法创建“EmailOptions”类型的实例,因为它缺少公共无参数构造函数。 System.InvalidOperationException:无法创建“EmailOptions”类型的实例,因为它缺少公共无参数构造函数。在Microsoft.Extensions.Configuration.ConfigurationBinder.CreateInstance(类型类型)
当然我可以在类中添加无参数构造函数,但是如何通过使用带参数依赖的构造函数来确保DI容器将创建我的类的实例?
从技术上讲,您可以尝试创建自己的IConfigureOptions实现。
表示配置TOptions类型的内容。注意:这些在所有IPostConfigureOptions之前运行。
所以做这样的事情:
public class ConfigureEmailOptions : IConfigureOptions<EmailOptions>
{
private readonly IEmailConfiguration _account;
public ConfigureMyOptions(IEmailConfiguration account)
{
_account = account;
}
public void Configure(EmailOptions options)
{
options.Configuration = _account;
...
}
}
并将其注册为
services.AddTransient<IConfigureOptions<EmailOptions>, ConfigureEmailOptions>();
你的选项类应该是公正的
public class EmailOptions
{
public string DefaultFromAddress { get; set; }
public string DefaultFromDisplayName { get; set; }
public IEmailConfiguration Configuration { get; set; }
}
根据配置在ASP.NET Core中的工作方式,它将始终使用无参数构造函数。虽然这不是唯一的原因,但一个特别好的理由是配置设置在任何DI服务注册之前发生,这意味着如果它想要它就不能注入任何东西。
无论长短,都无法在强类型配置类中满足IEmailConfiguration
之类的东西。无论如何,坦率地说这是一个坏主意。只需让您的配置类成为一个简单的实体,并将其注入服务或处理您的电子邮件的东西,而不是相反。
它说你需要一个公共无参数构造函数。
加
public EmailOptions() {
}