Fluent Interface en C#

Para quienes no conocen acerca de Fluent Interface les recomiendo este gran artículo escrito por los responsables de este estilo de programación: Eric Evans y Martin Fowler.

Básicamente la idea de esto es permitir escribir código de una manera más fluida y más comprensible de leer.

Para entender este concepto vayamos directamente al código. Supongamos que tenemos definida una clase que para representar e-mails:

public class Email
{
    public SmtpClient Client { get; set; }
    public string From { get; set; }
    public string To { get; set; }
    public string Subject { get; set; }
    public string Body { get; set; }

    public void Send()
    {
        // Enviar correo...
    }
}

Para crear una nueva instancia de Email lo que generalmente haríamos es lo siguiente:

SmtpClient client = new SmtpClient("host", 1);

Email email = new Email();
email.Client = client;
email.From = "from@sebys.com.ar";
email.To = "to@sebys.com.ar";
email.Subject = "Envio email";
email.Body = "Este es el contenido del e-mail";

email.Send();

Ahora bien, los que nos ofrece esta nueva técnica es poder inicializar un e-mail de la siguiente forma:

SmtpClient client = new SmtpClient("host", 1);

IEmail fluentEmail = new IEmail()
                         .Client(client)
                         .From("from@sebys.com.ar")
                         .To("to@sebys.com.ar")
                         .Subject("Envio email")
                         .Body("Este es el contenido del e-mail")
                         .Send();

Lo que hicimos acá es exponer todo el comportamiento que realmente nos interesa de la clase Email dentro de la clase IEmail. Para esto lo primero que debemos hacer es crear esta nueva clase y definir una propiedad privada del tipo Email y luego encapsular todo el comportamiento deseado:

public class IEmail
{
    private Email _email;

    public IEmail()
    {
        this.IEmail();
    }

    public IEmail IEmail()
    {
        this._email = new Email();
        return this;
    }

    public IEmail Client(SmtpClient client)
    {
        this._email.Client = client;
        return this;
    }

    public IEmail From(string from)
    {
        this._email.From = from;
        return this;
    }

    public IEmail To(string to)
    {
        this._email.To = to;
        return this;
    }

    public IEmail Subject(string subject)
    {
        this._email.Subject = subject;
        return this;
    }

    public IEmail Body(string body)
    {
        this._email.Body = body;
        return this;
    }

    public IEmail Send()
    {
        this._email.Send();
        return this;
    }
}

El secreto está en que cada uno de los métodos devuelve una instancia del objeto creado, por lo tanto podemos ir invocando nuevos métodos sin necesidad de hacer una nueva línea.

Esta es una forma de utilizar Fluent Interface, otra es hacerlo directamente en la clase EMail, también podemos crear una interfaz con los métodos que nos interesan de Email y las clases que implementen dicha interfaz sean nuestras “Fluent Interface“.