开发者

How to specify the implementation you want to inject

开发者 https://www.devze.com 2023-03-25 18:33 出处:网络
I\'m in the process of implementing a notification service. Essentially, customers can get notified in a number of ways, such as via email, text message, fax etc. Below is a rough implementation that

I'm in the process of implementing a notification service. Essentially, customers can get notified in a number of ways, such as via email, text message, fax etc. Below is a rough implementation that is not wired together.

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
    }
}

The NotificationService class essentially takes in a method of notification and a formatter. Obviously, each method of notification requires different formatting.

Based on business criteria, how do I sele开发者_运维技巧ct which implementation of INotification and NotificationFormatter I wish to use? Note that within the lifetime of the user using the application each notification will most likely be used. I say this because it's not as simple as instructing my container to inject implementation Foobar as it will change while the user is using the application.

I've thought of creating some sort of class that could handle pairs because it seems to makes sense to me that you wouldn't want use a text message notification formatter for a fax notification. However, I can't seem to wrap my head around a decent implementation of this.

I also own the book Dependency Injection in .NET by Mark Seemann. Did I perhaps miss something obvious?

Thank you.


How is it that you decide what kind of notification a user wants? If it can change while they're using your app, it seems like the NotificationService for that user msut be created anew for each notification you want to send them. That's ok - just use some sort of lookup to select a INotification impelmentation with an IoC container.

IoC's (I use AutoFac) let you use string-indexes to select a specific implementation. That string could come from a DB or whatever to represent the user's preference. Then you'd pass it to your IoC asking for an INotification 'decorated' with your string-choice. Upon startup, all the various implementations are registered with thier choice-strings.

I think you may be on to something with your 'pairs' comment - if INotificationFormat is closely tied to INotification and there is a possiblity of mixing them up then perhaps the INotification implementation itself should select its formatter.


What you need to do is to provide some kind of configuration infrastructure. For example, assuming that you want to keep the service just the way you've defined it, I would implement a factory returning an instance of NotificationService according to your model:

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;
    }
}

This implementation configures the factory using static list, you could use a IoC container if it supports this kind of operations.

0

精彩评论

暂无评论...
验证码 换一张
取 消