Passaggio dei valori di configurazione a un metodo utilizzando i principi SOLID

2

Ho una classe helper email che ha un metodo che invia email:

private static class EmailHelper
{
    public static void SendEmail(string from, string to, string subject, string message)
    {
        MailMessage msg = new MailMessage(from, to, subject, body);
        var client = new SmtpClient("my.smpthost.com"); //this will be moved to config.
        client.Send(msg);
    }
}

La mia stringa host smtp verrà inserita nel mio file di configurazione. Domanda è qual è il modo consigliato per passare l'host smtp a questo metodo?

  1. Dovrei avere un costruttore in questa classe che accetta la stringa smtp?
  2. Oppure, dovrei passare lo smtp come 5 ° parametro?
  3. O questo metodo dovrebbe essere letto direttamente dalla config?

(Capisco che ci possono essere diversi modi per farlo, ma sto cercando di capire l'approccio raccomandato, o almeno gli approcci che NON sono raccomandati, tenendo presente i principi SOLID.)

    
posta Prabhu 15.08.2014 - 22:07
fonte

1 risposta

1

Una soluzione molto semplice sarebbe quella di fob this off su configurazione .NET e utilizzare il costruttore senza parametri che catturerà le impostazioni SMTP dalla configurazione di questa app. Questo ti permetterà di iniettare i valori appropriati come richiesto e probabilmente la cosa più SOLIDA che potresti fare se rimani statico. Vedi la pagina man di microsoft sulla configurazione System.Net.Mail per ulteriori informazioni.

Ma dal momento che vuoi imparare qui inizierei eliminando l'intero metodo statico per l'invio dell'approccio alla posta elettronica - è decisamente meglio che gestire tutto questo a mano ogni volta che vuoi inviare un'email. Sarebbe molto meglio servire utilizzando un'interfaccia per fornire una facciata per l'invio di e-mail e quindi lo scambio di implementazioni come meglio credi. Quindi vorrete qualcosa come:

public interface IEmailService
{
    MessageSentResult SendMessage(MailMessage msg);
}

public class MessageSentResult
{
    public bool Successful { get; set; }
    public string ErrorCode { get; set; }
    public string ErrorMessage { get; set;}
    public MailMessage SentMessage { get; set; }
    public string FailedRecipients { get; set; }
}

Che potrebbe avere un'implementazione simile a:

    private readonly SmtpClient smtpClient;

    public SystemNetEmailService(SmtpClient smtpClient)
    {
        if (smtpClient == null) throw new ArgumentNullException("smtpClient");
        this.smtpClient = smtpClient;
    }

    public MessageSentResult SendMessage(MailMessage msg)
    {
        if (msg == null) throw new ArgumentNullException("msg");
        var res = new MessageSentResult()
                      {
                          SentMessage = msg,
                      };
        try
        {
            smtpClient.Send(msg);
            res.Successful = true;
            res.ErrorMessage = "No error.";
        }
        catch (SmtpFailedRecipientException mfex)
        {
            res.ErrorCode = mfex.StatusCode.ToString();
            res.ErrorMessage = "Some recipeints failed. See FailedRecipients for details.";
            res.FailedRecipients = mfex.FailedRecipient;
        }
        catch (SmtpException sex)
        {
            res.ErrorCode = sex.StatusCode.ToString();
            res.ErrorMessage = sex.Message;
            res.Successful = false;
        }
        return res;
    }

Il vantaggio principale qui è testabilità e swappability. Testabilità in quanto è possibile creare facilmente un'implementazione fittizia che non invia posta ma che potrebbe essere utilizzata nei test di unità per verificare che il messaggio sia corretto. Swappability significa che puoi fare cose come lo swap in un'implementazione completamente diversa come backhauling la tua posta su qualcosa come mailgun o mandrill perché hai capito che la consegna è importante.

    
risposta data 15.08.2014 - 22:19
fonte

Leggi altre domande sui tag