Как указать реализацию, которую вы хотите внедрить - PullRequest
4 голосов
/ 04 августа 2011

Я в процессе внедрения службы уведомлений. По сути, клиенты могут получать уведомления несколькими способами, например, по электронной почте, текстовым сообщениям, факсу и т. Д. Ниже приведена грубая реализация, которая не связана друг с другом.

public class NotificationService
{
    private readonly INotification _notification;
    private readonly INotificationFormatter _formatter;

    public NotificationService(
        INotificationMethod notification, 
        INotificationFormatter formatter)
    {
        _notification = notification;
        _formatter = formatter;
    }

    public void Notify(SomeParameterObject obj)
    {
        var formattedMessage = _formatter.Format(obj);
        _notification.SendNotification(formattedMessage);
    }
}

public interface INotificationFormatter
{
    NotificationMessage Format(SomeParameterObject obj);
}

public interface INotification
{
    void SendNotification();
}

public EmailNotification : INotification
{
    public void SendNotification(NotificationMessage message)
    {
        // Use Exchange Web Services to send email
    }
}

Класс NotificationService по существу принимает метод уведомления и форматер. Очевидно, что каждый метод уведомления требует различного форматирования.

На основании бизнес-критериев, как выбрать, какую реализацию INotification и NotificationFormatter я хочу использовать? Обратите внимание, что в течение срока действия пользователя, использующего приложение, наиболее вероятно будет использоваться каждое уведомление. Я говорю это потому, что это не так просто, как указание моему контейнеру внедрить реализацию Foobar, поскольку это изменится, когда пользователь использует приложение.

Я думал о создании какого-то класса, который мог бы обрабатывать пары, потому что мне кажется, что вы не захотите использовать средство форматирования уведомлений для текстовых сообщений для уведомления по факсу. Тем не менее, я не могу обернуться вокруг приличной реализации этого.

Мне также принадлежит книга «Инъекция зависимостей в .NET» Марка Симанна Возможно, я что-то упустил очевидное?

Спасибо.

Ответы [ 2 ]

4 голосов
/ 04 августа 2011

Как вы решаете, какое уведомление пользователь хочет? Если он может измениться, пока они используют ваше приложение, похоже, что NotificationService для этого пользователя будет создан заново для каждого уведомления, которое вы хотите отправить. Это нормально - просто используйте какой-то поиск для выбора имплементации INotification с контейнером IoC.

IoC (я использую AutoFac) позволяет использовать строковые индексы для выбора конкретной реализации. Эта строка может исходить из БД или чего-либо еще, чтобы представлять предпочтения пользователя. Затем вы передадите его в свой IoC с запросом на INotification, «украшенную» вашим выбором строк. После запуска все различные реализации регистрируются с помощью их строк выбора.

Я думаю, что вы, возможно, что-то обсуждаете со своими комментариями «пар» - если INotificationFormat тесно связан с INotification и есть возможность смешать их, то, возможно, сама реализация INotification должна выбрать свой форматер.

2 голосов
/ 05 августа 2011

Что вам нужно сделать, это предоставить некую инфраструктуру конфигурации.Например, предполагая, что вы хотите сохранить службу именно так, как вы ее определили, я бы реализовал фабрику, возвращающую экземпляр NotificationService в соответствии с вашей моделью:

public struct NotificaitonSettings<T>
{
    public Predicate<T> Predicate;
    public NotificationService Service;
}

public class NotificationServiceFactory<T> : INotificationServiceFactory<T>
{
    protected static List<NotificaitonSettings<T>> settings = new List<NotificaitonSettings<T>>();

    static NotificationServiceFactory()
    {
        settings.Add(new NotificaitonSettings<T>
        {
            Predicate = m => !String.IsNullOrEmpty(m.Email),
            Service = new NotificationService(new EmailNotification(), new EmailFormatter())
        });
        settings.Add(new NotificaitonSettings<T>
        {
            Predicate = m => !String.IsNullOrEmpty(m.Fax),
            Service = new NotificationService(new FaxNotification(), new FaxFormatter())
        });
    }

    public NotificationService Create(T model)
    {
        return settings.FirstOrDefault(s => s.Predicate(model)).Service;
    }
}

Эта реализация настраивает фабрику, используястатический список, вы можете использовать контейнер IoC, если он поддерживает операции такого типа.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...