views:

96

answers:

3

Know this has been asked before, however my question is slightly different.

I have an interface:

IEmailDispatcher

It looks like this:

public interface IEmailDispatcher
{
    void SendEmail(string[] to, string fromName, string fromAddress, string subject, string body, bool bodyIsHTML, Dictionary<string, byte[]> Attachments);
}

As a bit of background:

I have a static EmailDispatcher class that has the method: SendEmail(string[] to, string fromName, string fromAddress, string subject, string body, bool bodyIsHTML, Dictionary Attachments);

This, throught IoC, then loads the relevant IEmailDispatcher implementation, and calls that method.

My applications can then simply call EmailDispatcher.SendEmail(.........

I want to add events to it, for example OnEmailSent, OnEmailFail etc... So that each implementation can handle successes and failures of sending emails, and log them accordingly.

How would I go about doing this?

Or, is there a better way?

At the moment, I'm using a "BasicEmailDispatcher" that basically uses the System.Net namespaces, creates a MailMessage, and sends it.

In the future, I will create another class, that handles mail differently... adds it to a sql db table for reporting etc.... and so will handle the OnEmailSent events differently to the BasicEmailDispatcher

+1  A: 
public interface IEmailDispatcher
{
    event EventHandler EmailSent;
    void SendEmail(string[] to, string fromName, string fromAddress, string subject, string body, bool bodyIsHTML, Dictionary<string, byte[]> Attachments);
}

For more details, look here.

Is this the answer you were looking for?

Phil
A: 

Add the events to your interface :

public interface IEmailDispatcher
{
    void SendEmail(string[] to, string fromName, string fromAddress, string subject, string body, bool bodyIsHTML, Dictionary<string, byte[]> Attachments);
    event EmailSentEventHandler EmailSent;
    event EmailFailedEventHandler EmailFailed;
}

And in your static class, use explicit event accessors to subscribe to the events of the actual implementation :

public static class EmailDispatcher
{
    public event EmailSentEventHandler EmailSent
    {
        add    { _implementation.EmailSent += value; }
        remove { _implementation.EmailSent -= value; }
    }

    public event EmailFailedEventHandler EmailFailed
    {
        add    { _implementation.EmailFailed += value; }
        remove { _implementation.EmailFailed -= value; }
    }
}
Thomas Levesque
+2  A: 

It looks like trying to fit everything into the static class is making you do awkward things here (specifically, implementing the template pattern using a static class). If callers (applications) only need to know about the SendEmail method, that's the only thing that should be in the interface.

If that is indeed the case, you can just make your base dispatcher class implement the template pattern:

public class EmailDispatcherBase: IEmailDispatcher {
    // cheating on the arguments here to save space
    public void SendEmail(object[] args) {
        try {
            // basic implementation here
            this.OnEmailSent();
        }
        catch {
            this.OnEmailFailed();
            throw;
        }
    }
    protected virtual  void OnEmailSent() {}
    protected virtual  void OnEmailFailed() {}
}

More complex implementations would each inherit from BasicEmailDispatcher (and therefore implement IEmailDispatcher) and override one or both of the virtual methods to provide success or failure behavior:

public class EmailDispatcherWithLogging: EmailDispatcherBase {
    protected override OnEmailFailed() {
        // Write a failure log entry to the database
    }
}
Jeff Sternal
I'm not sure how to implement this-Where does my static class fit in? The "entry point" from the callers...?For example, I have BasicEmailDispatcher, DummyEmailDispatcher... do they still implement IEmailDispatcher? or BaseEmailDispatcher...
alex
Also - what causes each EmailSent and EmailFailed event will be different in each implementation....
alex
Sorry - I misunderstood your requirements somewhat! In the process of revising my answer, I've tried to clarify it a bit too. As for your static class, it's really a separate issue - you can keep using it as you've been doing. (Though I recommend reading around on StackOverflow about singletons and dependency injection!)
Jeff Sternal