如何指定要注入的实现

时间:2011-08-04 17:56:27

标签: c# dependency-injection

我正在实施通知服务。从本质上讲,客户可以通过多种方式获得通知,例如通过电子邮件,短信,传真等。以下是一个未连接在一起的粗略实现。

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类基本上采用了通知方法和格式化程序。显然,每种通知方法都需要不同的格式。

根据业务标准,如何选择我希望使用的INotificationNotificationFormatter实施?请注意,在使用应用程序的用户的生命周期内,很可能会使用每个通知。我这样说是因为它并不像指示我的容器注入实现Foobar那么简单,因为它会在用户使用应用程序时发生变化。

我曾想过创建一些可以处理对的类,因为我觉得你不想使用短信通知格式化器来传真通知。但是,我似乎无法绕过一个体面的实现。

我还拥有Mark Seemann在.NET中的Dependency Injection这本书。我可能会错过一些明显的东西吗?

谢谢。

2 个答案:

答案 0 :(得分:4)

您如何确定用户想要的通知类型?如果它在使用您的应用时可能会发生变化,则似乎会为您要发送的每个通知重新创建该用户的NotificationService。没关系 - 只需使用某种查找来选择IoC容器的INotification impelmentation。

IoC(我使用AutoFac)允许您使用字符串索引来选择特定的实现。该字符串可以来自数据库或代表用户偏好的任何内容。然后你将它传递给你的IoC,要求用你的字符串选择'装饰'。启动时,所有各种实现都使用其选择字符串进行注册。

我认为你可能会对你的'对'评论有所了解 - 如果INotificationFormat与INotification密切相关并且有可能将它们混合起来,那么也许INotification实现本身应该选择它的格式化程序。

答案 1 :(得分:2)

您需要做的是提供某种配置基础架构。例如,假设您希望按照您定义的方式保留服务,我将根据您的模型实现返回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容器。