.NET核心-根据运行时的条件,实现接口的最佳实践是什么



我正在开发电子邮件服务,该服务可以使用IMAP、SMTP或第三方软件(如SendGrid(发送电子邮件。

我需要确定哪个服务将在运行时处理发送过程,因为用户将指定将使用哪个提供程序(在请求中有一个名为ProviderType的属性(。

那么,实施这一过程的最佳方法是什么呢。

我试图根据提供程序类型实现一个名为IEmailSender的接口,但我失败了。

我正在使用.Net core 6

这是一个非常粗糙的实现,但应该能让你明白。

为电子邮件发件人声明您的界面,例如

public interface IEmailSender
{
Task SendAsync(string to, string body);
}

为每种风格添加实现类,例如

public class SmtpEmailSender : IEmailSender
{
private readonly IOptions<SmtpOptions> _options;
private readonly ISmtpClient _client;
public SmtpEmailSender(IOptions<SmtpOptions> options, ISmtpClient client)
{
_options = options;
_client = client;
}
public async Task SendAsync(string to, string body)
{ /* smtp logic */ }
}
public class SendGridEmailSender : IEmailSender
{
private readonly ISendGridClient _sendGridClient;
public SendGridEmailSender(ISendGridClient sendGridClient)
{ _sendGridClient = sendGridClient; }
public async Task SendAsync(string to, string body) { /* smtp logic*/ }
}
public class IMapEmailSender : IEmailSender
{
public async Task SendAsync(string to, string body) { ... }
}

根据您的意愿,每一个都可以有自己的依赖项。

添加一个工厂类(如果你想的话,也有一个接口。为了保持简单,省略了它(

public class EmailSenderFactory
{
private readonly IServiceProvider _serviceProvider;
public EmailSenderFactory(IServiceProvider serviceProvider)
{ _serviceProvider = serviceProvider; }
public IEmailSender GetEmailSender(string senderType)
{
return senderType switch
{
"smtp"     => _serviceProvider.GetRequiredService<SmtpEmailSender>(),
"sendgrid" => _serviceProvider.GetRequiredService<SendGridEmailSender>(),
"imap"     => _serviceProvider.GetRequiredService<IMapEmailSender>(),
"other"    => _serviceProvider.GetRequiredService<OtherType>(),
_          => throw new Exception("No sender configured for this") // handle case of provider not found 
};
}
}

注册每个实现,包括工厂类。

builder.Services.AddScoped<SendGridEmailSender>(); // or service.Add if in Startup.cs
builder.Services.AddScoped<IMapEmailSender>();
builder.Services.AddScoped<SmtpEmailSender>();
builder.Services.AddScoped<EmailSenderFactory>();

在您的使用中,注入EmailSenderFactory并从中解析一个IEmailSender

public class SomeController
{
private readonly EmailSenderFactory _factory;
public SomeController(EmailSenderFactory factory)
{ _factory = factory; }
[HttpPost]
public async Task<ActionResult> SendEmail(RequestModel requestModel)
{
var sender = _factory.GetEmailSender(requestModel.ProviderType);
await sender.SendAsync(...);
}
}

最新更新