Use an enum to select which class to instantiate

Robert picture Robert · Jul 24, 2013 · Viewed 7.5k times · Source

I have an enum that I am trying to associate to dto's:

 public enum DtoSelection
 {
     dto1,
     dto2,
     dto3,
 }

There are 108 and values in this enum.

I have a dto object for each of these dto's:

 public class dto1 : AbstractDto
 {
       public int Id { get; set; }
       //some stuff specific to this dto
 }

I am trying to make a method (eventually a service) that will return me a new dto object of the type associated to the the dto in question:

 private AbstractDto(int id)
 {
      if (id == DtoSelection.Dto1.ToInt()) //extension method I wrote for enums
            return new Dto1();
      if (id == DtoSelection.Dto2.ToInt())
            return new Dto2();
 }

Obviously I do not want to do this 108 times. For whatever reason my brain is just missing something obvious. What is the best way to handle this.

Answer

Trevor Pilley picture Trevor Pilley · Jul 24, 2013

This class will do what you want as long as the Dto classes are defined in the same namespace as AbstractDto (you'll need to tweak it if not):

Given the following enums and classes:

public enum DtoSelection
{
    Dto1,
    Dto2,
    Dto3,
}

public abstract class AbstractDto
{
}

public class Dto1 : AbstractDto
{
}

public class Dto2 : AbstractDto
{
}

public class Dto3 : AbstractDto
{
}

This method will resolve them:

public static class DtoFactory
{
    public static AbstractDto Create(DtoSelection dtoSelection)
    {
        var type = Type.GetType(typeof(AbstractDto).Namespace + "." + dtoSelection.ToString(), throwOnError: false);

        if (type == null)
        {
            throw new InvalidOperationException(dtoSelection.ToString() + " is not a known dto type");
        }

        if (!typeof(AbstractDto).IsAssignableFrom(type))
        {
            throw new InvalidOperationException(type.Name + " does not inherit from AbstractDto");
        }

        return (AbstractDto)Activator.CreateInstance(type);
    }
}