Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-core/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Asp.net core 具有构造函数依赖关系的AspNetCore选项模式_Asp.net Core_Asp.net Core Mvc - Fatal编程技术网

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

Asp.net core 具有构造函数依赖关系的AspNetCore选项模式,asp.net-core,asp.net-core-mvc,Asp.net Core,Asp.net Core Mvc,我有一个选项类,如下所示 public class EmailOptions { public EmailOptions(IEmailConfiguration account) { this.Configuration = account; } public string DefaultFromAddress { get; set; } public string DefaultFromDisplayName { get; set; }

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

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; }
}

我确信我正在向注册正确的实现

services.AddTransient<IEmailConfiguration, ApiKeyConfiguration>();
services.AddTransient();
但是,当我尝试将IOption注入控制器时,会出现以下错误:

[13:56:26错误]发生未经处理的异常:无法创建“EmailOptions”类型的实例,因为它缺少公共无参数构造函数。 System.InvalidOperationException:无法创建“EmailOptions”类型的实例,因为它缺少公共无参数构造函数。 位于Microsoft.Extensions.Configuration.ConfigurationBinder.CreateInstance(类型)


当然,我可以将无参数构造函数添加到类中,但如何确保DI容器通过使用具有参数依赖性的构造函数来创建我的类的实例?

这是说您需要一个公共的无参数构造函数


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


长话短说,在强类型配置类中无法满足类似于
IEmailConfiguration
的要求。坦白说,这是个坏主意。让您的配置类成为一个简单的实体,并将其注入到处理电子邮件内容的服务或其他东西中,而不是反过来。

从技术上讲,您可以尝试创建自己的实现

表示配置Topions类型的内容。注意:这些是在所有IPostConfigureOptions之前运行的

因此,请这样做:

public class ConfigureEmailOptions : IConfigureOptions<EmailOptions>
{
    private readonly IEmailConfiguration _account;
    public ConfigureMyOptions(IEmailConfiguration account)
    {
        _account = account;
    }

    public void Configure(EmailOptions options)
    {
        options.Configuration = _account;
        ...
    }
}

:这是非常清楚的。但是,我是否确保通过使用带参数的构造函数来创建选项?我知道通常DI容器总是使用具有大多数参数的构造函数,但在我的例子中,这正是必需的。
public EmailOptions() {

}
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; }
}