user3655934
user3655934

Reputation:

Mapping Enum values to Classes

I want to be able to map each value of an Enum to a different class (and the reverse), but keep the relationships stored in a single place so they can be altered/added to without making changes in multiple location.

What pattern would allow me map Enum values to Classes?

My specific usage is roughly as follows:

I have a Person class that holds general information about the person. To this class can be added components (stored in a List Dictionary) that hold information specific to a particular type of person, eg. componentCustomer, componentEndUser, componentSupplier. These component-classes implement an IPersonComponent interface. Importantly, a person can be more than one type and can therefore hold more than one component.

I also have an Enum ePersonType with values eg. Customer, End User, Supplier. Each value has a one-to-one relationship with a component.

When a person's record is retrieved, a List<int> is populated with the appropriate 'ePersonType' values. This list is then used to determine what components need to be allocated to the Person and loaded with data.

Clearly, it is straightforward to switch on the person's types and add components appropriately. However, what if I later want to check what components the person instance holds and what ePersonTypes they are? I could switch back on component.GetType(), but then I am storing the relationship in two places.

Alternatively, I could store the appropriate ePersonType inside each component and use Linq to check whether an person instance has a particular component, but then it seems like the original allocation would be more complex, possibly requiring reflection?

I feel sure that I'm missing something really obvious here.

Upvotes: 0

Views: 4360

Answers (1)

rossipedia
rossipedia

Reputation: 59467

One of the ways I've approached this is to use an attribute on the actual enum values:

public enum PersonType
{
  [PersonClass(typeof(Customer)]
  Customer,

  [PersonClass(typeof(EndUser)]
  EndUser,

  [PersonClass(typeof(Supplier)]
  Supplier,
}

public class PersonClassAttribute : System.Attribute 
{
    public Type Type { get; }

    public PersonClassAttribute(Type type)
    {
        Type = type;
    }
}

Then use a static class for managing the retrieval and mapping of enums to types:

public static class People
{
    static Dictionary<PersonType, Type> mapping = new Dictionary<PersonType, Type>();

    static People()
    {
        var fields = Enum.GetNames(typeof(PersonType)).Select(n => typeof(PersonType).GetFieldr(n));
        mapping = fields.ToDictionary(
            f => (PersonType)f.GetRawConstantValue(),
            f => f.GetCustomAttribute<PersonClassAttribute>().Type
            );
    }


    public static T GetPersonInstance<T>(this PersonType type)
    {
       return (T)Activator.CreateInstance(mapping[type]);
    }
}

Obviously there'd be a bit more to it (validation, error checking, etc), but that's the general idea.

Upvotes: 4

Related Questions