C # Получение типа публичной переменной на основе значения Enum - PullRequest
6 голосов
/ 22 января 2010

У меня есть класс, который анализирует данные из текстового файла с разделителями-запятыми. У меня есть перечисление для полей, чтобы помочь мне разобрать данные проще. Класс, который анализирует все записи, содержит открытые переменные для каждого поля и, конечно, их типы переменных. Мне нужно получить тип этих переменных на основе указанного перечисления.

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 все назначаются в моем конструкторе. Однако я хочу получить эти типы, даже не создавая экземпляр DataBaseRecordInfo. Прямо сейчас мой статический метод, описанный выше, будет работать, однако, если я захочу изменить тип переменной, мне придется изменить его в 2 местах. Есть ли способ обойти необходимость изменить это в обоих местах и ​​сохранить его как статический метод?

Ответы [ 4 ]

4 голосов
/ 22 января 2010

Если имя всегда будет точно соответствовать, вы можете сделать это с помощью отражения.

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

Вы можете даже кэшировать эти значения в словаре, поэтому, если он найден, просто верните запись словаря, в противном случае определите, используя отражение, и кэшируйте результат.

0 голосов
/ 23 января 2010

Если вы хотите связать значение перечисления с некоторой дополнительной информацией, вы можете использовать свой собственный атрибут CustomAttribute.

Может быть, вам нужно что-то вроде этого:

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());
0 голосов
/ 22 января 2010

Как насчет этого:

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);
  }
}

Я знаю, что вы сказали, что никогда не создавали экземпляр DataBaseRecordInfo, но я предполагаю, что вы имели в виду экземпляр вне статического метода. Никто никогда не видит этот экземпляр.

0 голосов
/ 22 января 2010

Да, вы можете использовать имена в перечислении вместе с отражением типа DatabaseRecordInfo, чтобы получить нужные вам типы.

Это можно сделать так:

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;
    }
};

Возможно, вы захотите кэшировать результат в словаре, поскольку отражение может быть дорогостоящим с точки зрения производительности.

...