使用IOption的类的实例化

问题描述 投票:1回答:4

在ASP.NET Core 2.1中,我有一个类来发送使用IOptions接口的电子邮件,如下所示:

public class Email
{
    private readonly ManuelaIbiEmail manuelaIbiEmail;

    public Email(IOptions<ManuelaIbiEmail> manuelaIbiEmail)
    {
        this.manuelaIbiEmail.Username = manuelaIbiEmail.Value.Username;
        this.manuelaIbiEmail.Password = manuelaIbiEmail.Value.Password;
    }

    public async Task SendAsync(Contato contato)
    {
        var smtpClient = new SmtpClient
        {
            Host = "smtp.sendgrid.net",
            Port = 587,
            EnableSsl = true,
            Credentials = new NetworkCredential(manuelaIbiEmail.Username, manuelaIbiEmail.Password)
        };

        using (var message = new MailMessage(contato.Email, "[email protected]")
        {
            Subject = "Email de Manuela Ibi Nutrição Integrada",
            Body = $"{contato.Comentario}\nTelefone: {contato.Telefone}"
        })
        {
            await smtpClient.SendMailAsync(message);
        }
    }
}

这个类必须在控制器中实例化,例如“var whatever = new Email(???);”以便可以调用SendAsync方法。

但这里的大图是我在这个初始化中丢失了。我只是不知道在“电子邮件(某事)”中要叫什么。

只是,需要提供更多信息以便:

系统应该从Secrets读取用户名,密码,因此我在Startup.cs中有以下行:

services.Configure<ManuelaIbiEmail>(Configuration.GetSection("ManuelaIbiEmail"));

ManuelaIbiEmail是一个非常简单的POCO类:

public class ManuelaIbiEmail
{
    public string Username { get; set; }
    public string Password { get; set; }
}

控制器看起来像:

public class ContactController : Controller
{
    private readonly ManuelaIbiEmail manuelaIbiEmail;

    public IActionResult Contact()
    {
        return View(new Contato());
    }

    [HttpPost]
    public async Task<IActionResult> ContactAsync(Contato contato)
    {
        var email = new Email();
        email.SendAsync(contato);

        return Ok();
    }
}

如果有人能够善意地告诉我我错过了什么,我会很感激。

先感谢您

c# asp.net-mvc asp.net-core dependency-injection
4个回答
4
投票

依赖注入的全部意义不是那样做。

您可以通过属性在方法中注入它:

public class ContactController : Controller
{
    public IActionResult Contact()
    {
        return View(new Contato());
    }

    [HttpPost]
    public async Task<IActionResult> ContactAsync(Contato contato, [FromServices]Email email)
    {
        email.SendAsync(contato);

        return Ok();
    }
}

或者通过构造函数注入:

public class ContactController : Controller
{
    private readonly EMail email;

    public ContactController(Email email)
    {
        this.email = email;
    }

    public IActionResult Contact()
    {
        return View(new Contato());
    }

    [HttpPost]
    public async Task<IActionResult> ContactAsync(Contato contato)
    {
        email.SendAsync(contato);

        return Ok();
    }
}

1
投票

只需通过构造函数注入Email

public class ContactController : Controller
{
    public ContactController(Email email)
    {
        Email = email;
    }

    public Email Email { get; }

    public IActionResult Contact()
    {
        return View(new Contato());
    }

    [HttpPost]
    public async Task<IActionResult> ContactAsync(Contato contato)
    {
        Email.SendAsync(contato);

        return Ok();
    }
}

1
投票

理想情况下,您不希望通过手动初始化Email将控制器与实现问题紧密耦合,因为类应取决于抽象而非结果。

摘要电子邮件类

public interface IEmail {
    Task SendAsync(Contato contato);
}

public class Email: IEmail {
    //...omitted for brevity
}

你可以通过构造函数注入将它注入控制器

public class ContactController : Controller {
    private readonly IEmail email;

    public ContactController(IEmail email) {
        this.email = email;
    }

    public IActionResult Contact() {
        return View(new Contato());
    }

    [HttpPost]
    public async Task<IActionResult> ContactAsync(Contato contato) {        
        await email.SendAsync(contato);
        return Ok();
    }
}

配置正确后

services.AddTransient<IEmail, Email>();

容器将在创建注入对象图时解析所有依赖项。


-2
投票

我的主张:

Create一个IOption实例并使用此实例初始化您的类Email

using Microsoft.Extensions.Options;

var mail = new ManuelaIbiEmail() { Username= "", Password="" };
IOptions<ManuelaIbiEmail> options = Options.Create(mail);
var email = new Email(options);
© www.soinside.com 2019 - 2024. All rights reserved.