Как я могу использовать DI с классами электронной почты и SMS - PullRequest
0 голосов
/ 28 января 2019

У меня есть этот интерфейс:

public interface IMessageSender
{
    Task SendMessageAsync(parameters);
}

И это классы:

public class EmailSender : IMessageSender
{
}

public class SMSSender : IMessageSender
{
}

В моем контроллере я использовал их так:

public class MyController : Controller
{
    private readonly IMessageSender _messageSender;
    public MyController(IMessageSender messageSender)
    {
        _messageSender = messageSender;
    }
}

ИУ меня есть два метода в этом контроллере:

public async Task<IActionResult> SendByEmail()
{ 
    await _messageSender.SendMessageAsync(parameters);
}

public async Task<IActionResult> SendBySMS()
{ 
    await _messageSender.SendMessageAsync(parameters);
}

В вышеупомянутых методах, как я могу сказать ядру .net, что в методе SendByEmail мне нужен экземпляр класса EmailSender иметод SendBySMS, мне нужен экземпляр класса SMSSender.Я уже добавил это в мой класс запуска, но он всегда создает экземпляр класса EmailSender:

services.AddTransient<IMessageSender, EmailSender>();

1 Ответ

0 голосов
/ 28 января 2019

В настоящее время у вас есть:

public interface IMessageSender
{
    Task SendMessageAsync(parameters);
}

и два класса, которые реализуют этот интерфейс.Это работает, но я бы предложил немного изменить этот подход.Сохраните IMessageSender и добавьте два новых интерфейса:

public interface IEmailSender : IMessageSender
{
}

public interface ISMSSender : IMessageSender
{
}

Зачем это нужно?Что ж, теперь он позволяет вам вводить в конкретного отправителя, который вас интересует (этот контроллер хочет отправлять электронные письма, этот контроллер хочет отправлять SMS).

Кроме того, поскольку они оба наследуются от IMessageSender, с некоторыми контейнерами IoC (например, Autofac - я не проверял их все), вы также можете добавить коллекцию IMessageSender (то есть IEnumerable<IMessageSender>) -это не всегда полезно, но может быть полезно, если вы хотите вызвать всех отправителей сообщения (т. е. отправьте SMS по этому номеру и по электронной почте).Если это бесполезно - не проблема, удалите IMessageSender в целом (и переместите методы, определяющие интерфейс, в IEmailSender и ISMSSender).

Теперь измените классы, чтобы реализовать новыеинтерфейсы:

public class EmailSender : IEmailSender
{
}

public class SMSSender : ISMSSender
{
}

и зарегистрируйте ваши классы для обоих интерфейсов в вашем контейнере. С Autofac это было бы что-то вроде AsImplementedInterfaces.

Глядя на ваш существующий код, я бы предложил следующее решение:

services.AddTransient<IEmailSender, EmailSender>();
services.AddTransient<ISMSSender, SMSSender>();
services.AddTransient<IMessageSender, EmailSender>();
services.AddTransient<IMessageSender, SMSSender>();

Затем измените ваш контроллердо:

public MyController(IEmailSender emailSender, ISMSSender smsSender)
...