开发者

Designing set of rules that use dependencies

I have a service that reads all emails as they get received in a specific mailbox. The issue is that based on what the email contains we have to do one or many actions. I currently have the mess below. I've shortened it quite a bit. The actual application currently has far more corner cases.

var email = new Email { Body = "Some random email body text..." };

if(email.Body.StartsWith("A"))
{
    // Requires a dependency on INotifier
    Console.WriteLine("Notifying administrator");
}
if (email.Body.StartsWith("B"))
{
    // Requires a dependency on IParser and IRepository
    Console.WriteLine("Parsing email and adding to database");
}
if (email.Body.EndsWith("C"))
{
    // Requires a dependency on ISender and INotifier
    Console.WriteLine("Forwarding email and notifying administrator");
}
if (email.Body.EndsWith("C"))
{
    // Requires a dependency on INotifier
    Console.WriteLine("Ignoring email");
}

Essentially, if a criteria is met then an associating action must get executed using one or more dependencies. These dependencies are something I'd like to inject in the constructor.

I've thought of creating something like this:

public class AdministratorNotififerCriteria : ICriteria
{
    private readonly INotifier _notifier;

    public AdministratorNotififerCriteria(INotifier notifier)
    {
        _notifier = notifier;
    }

    private void Execute()
    {
        _notifier.Notify();
    }

    public void CheckSatisfaction(Email email)
    {
        if(email.Body.StartsWith("A"))
            Execute();
    }
}

The bottom line is that I wish to make composable commands. So when I add another criteria down the line then all I have to do is inherit from ICriteria (or whatever) and let the application figure it out.

Is there a name for all of this?

I currently have a consumer that resembles this.

public class EmailConsumer
{
    private readonly IEnumerable<ICriteria> _criterias;

    // Criterias are found and injected with Windsor from all classes inheriting the ICriteria interface
    public EmailConsumer(IList<ICriteria> criterias)
    {
        _criterias = criterias;
    }

    public void Consume(IList<Email> emails)
    {
        foreach(var criteria in _criterias)
        {
            foreach(var email in emails)
            {
                criteria.CheckSatisfaction(email);
            }
        }
    }
}

Edit

Thanks for the replies, IAbstract and djna. I now understand what the strategy and CoR pattern do and thinking about which is more appropriate is proving that I don't understand enough of my current problem.

The way I开发者_如何学运维 understand it is that CoR is greedy and whoever can take responsibility will execute and proceed to the next object to be consumed. On the other hand, there doesn't seem to be anything stopping from looping between strategies that says "Hey! I can consume this request properly so don't worry about it".


This seems like a variation of Chain of responsibility with possibly some extra logic for dealing with non-exclusive cases - what do you intend should happen if the Body starts with "A" and ends with "C"?

One idea in Chain of Resposibility is that there's no need for a huge dispatching if/else chain. Instead you just offer the email to some ICriteria implementatio, and they have responsibility either to process or pass on to the next candidate.


@djna suggests a variation of the CoR pattern. I don't completely disagree. It seems more like this example of the Strategy Pattern.

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜