Question

I have a class that parses in data from a comma delimited text file. I have an enum for the fields to help me parse data in easier. The class that parses all the records in holds public variables for each field, and of course their variable types. I need to get the type of these variables based on the enum given.

public enum DatabaseField : int
    {
        NumID1 = 1,
        NumID2 = 2,
        NumID3 = 3,
    };

public class DataBaseRecordInfo
    {
        public long NumID1 { get; set; }
        public int NumID2 { get; set; }
        public short NumID3 { get; set; }

        public static Type GetType(DatabaseField field)
        {
           Type type;

           switch (field)
           {
               case DatabaseField.NumID1:
                   type = typeof(long);
                   break;
               case DatabaseField.NumID2:
                   type = typeof(int);
                   break;
               case DatabaseField.NumID3:
                   type = typeof(short);
                   break;
               default:
                   type = typeof(int);
                   break;
           }

           return type;
        }
     };

NumID1, NumID2, NumID3 all get assigned within my constructor. However, I want to get these types without ever creating an instance of DataBaseRecordInfo. Right now my static method above would work, however, if I wanted to change the variable type, I would have to change it in 2 places. Is there a way to get around having to change this in both places and keep it as a static method?

Was it helpful?

Solution

If the name is always going to match exactly you can do this using reflection.

return typeof(DataBaseRecordInfo)
    .GetProperty(field.ToString(), BindingFlags.Public | BindingFlags.Instance)
    .PropertyType;

You could even cache these values in a dictionary, so if found, just return the dictionary entry, otherwise determine using reflection and cache the result.

OTHER TIPS

Yes, you can use the names in the enum together with reflection on the DatabaseRecordInfo type to get the types you need.

This could be done like this:

public class DataBaseRecordInfo
{
    public long NumID1 { get; set; }
    public int NumID2 { get; set; }
    public short NumID3 { get; set; }

    public static Type GetType(DatabaseField field)
    {
        string name = field.ToString();
        Type recordType = typeof (DataBaseRecordInfo);
        var props = recordType.GetProperties();
        var matchedProperty = props.Where(p => name == p.Name).FirstOrDefault();
        if (matchedProperty == null)
            return null;    // We do not have a matching property.
        return matchedProperty.PropertyType;
    }
};

You will probably want to cache the result in a dictionary, since the reflection can be expensive performance-wise.

How about something like this:

public static Type GetType(DatabaseField field)
{
  DataBaseRecordInfo dbri = new DataBaseRecordInfo();

  switch (field)
  {
    case DatabaseField.NumID1:
      return dbri.NumID1.GetType(); 
    case DatabaseField.NumID2:
      return dbri.NumID2.GetType(); 
    case DatabaseField.NumID3:
     return dbri.NumID3.GetType(); 
    default:
      return typeof(int);
  }
}

I know you said without ever having to create an instance of DataBaseRecordInfo but I'm assuming you meant an instance outside of the static method. No one ever sees this instance.

If you want to bind enum value with some additional information you can use your own CustomAttribute.

Maybe you need something like this:

public class DatabaseTypeAttribute : Attribute
{
    public DatabaseTypeAttribute(Type type)
    {
        Type = type;
    }
    public Type Type { get; private set; }
}

public enum DatabaseField : int
{
    [DatabaseType(typeof(long))]
    NumID1 = 1,
    [DatabaseType(typeof(int))]
    NumID2 = 2,
    [DatabaseType(typeof(short))]
    NumID3 = 3,
    NumID4 = 4,
};

public static class DatabaseFieldHelper
{
    public static Type GetDatabaseType(this DatabaseField field)
    {
        var attributes = (DatabaseTypeAttribute[])typeof(DatabaseField).GetField(Enum.GetName(typeof(DatabaseField), field))
            .GetCustomAttributes(typeof(DatabaseTypeAttribute), false);
        if (attributes.Length == 0)
            return typeof(int); //returns default type
        return attributes[0].Type;

    }
}

//prints: NumID1 database type: System.Int64
Console.WriteLine("NumID1 database type: {0}", DatabaseField.NumID1.GetDatabaseType());

//prints: NumID2 database type: System.Int32
Console.WriteLine("NumID2 database type: {0}", DatabaseField.NumID2.GetDatabaseType());

//prints: NumID3 database type: System.Int16
Console.WriteLine("NumID3 database type: {0}", DatabaseField.NumID3.GetDatabaseType());

//prints: NumID4 database type: System.Int32
Console.WriteLine("NumID4 database type: {0}", DatabaseField.NumID4.GetDatabaseType());
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top