具有构造函数依赖关系的AspNetCore选项模式

问题描述 投票:0回答:3

我有一个选项类,如下所示

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容器将创建我的类的实例?

asp.net-core asp.net-core-mvc
3个回答
1
投票

从技术上讲,您可以尝试创建自己的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; }
}

1
投票

根据配置在ASP.NET Core中的工作方式,它将始终使用无参数构造函数。虽然这不是唯一的原因,但一个特别好的理由是配置设置在任何DI服务注册之前发生,这意味着如果它想要它就不能注入任何东西。

无论长短,都无法在强类型配置类中满足IEmailConfiguration之类的东西。无论如何,坦率地说这是一个坏主意。只需让您的配置类成为一个简单的实体,并将其注入服务或处理您的电子邮件的东西,而不是相反。


0
投票

它说你需要一个公共无参数构造函数。

public EmailOptions() {

}
© www.soinside.com 2019 - 2024. All rights reserved.