Search code examples
c#castingstrong-typing

Generic way to format object as subject and body?


I am trying to take a list of objects and format these as an email subject and body. To illustrate what I am doing, take the following examples:

public string GetSubject(Person myPerson) 
{ 
    return String.Format("To {0}", myPerson.Name); 
}

public string GetMessage(Person myPerson) 
{ 
    return String.Format("Dear {0}, Your new salary: {1}", 
        myPerson.Name, myPerson.Salary); 
}

public string GetSubject(VacationDay dayOff) 
{ 
    return String.Format("Vacation reminder!"); 
}

public string GetMessage(VacationDay dayOff) 
{ 
    return String.Format("Reminder: this {0} is a vacation day!", dayOff.Name); 
}

Later I have a bunch of emails which I want to send in a batch:

// myEmailObjects is a "List<object>"
foreach (var emailItem in myEmailObjects)
{
    SendEmail(from, to, GetSubject(emailItem), GetMessage(emailItem));
}

The problem is this code doesn't compile because the compiler can't resolve which GetSubject and which GetMessage routine to call. Is there any generic way to write this without using an is or as operator all over the place to check for types?


Solution

  • This is what interfaces are made for. Conceptually, an interface is like a contract that a class can sign where it obliges to define the methods that the interface specifies. Define each of the GetSubject() and GetMessage() methods as member methods of the corresponding classes instead, and then create the following interface:

    public interface IEmailable {
        string GetSubject();
        string GetMessage();
    }
    

    Then, make all of the involved classes implement the interface:

    public class VacationDay : IEmailable
    

    You can now create a List<IEmailable>(), and you may call those two methods on its elements.