【问题标题】:C# Getting the Type of a Public Variable based on an Enum valueC#根据枚举值获取公共变量的类型
【发布时间】:2011-01-08 07:50:27
【问题描述】:

我有一个从逗号分隔的文本文件中解析数据的类。我有一个字段枚举,可以帮助我更轻松地解析数据。解析所有记录的类为每个字段保存公共变量,当然还有它们的变量类型。我需要根据给定的枚举来获取这些变量的类型。

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 的实例的情况下获得这些类型。现在我上面的静态方法可以工作,但是,如果我想改变变量类型,我必须在两个地方改变它。有没有办法避免在这两个地方都进行更改并将其保留为静态方法?

【问题讨论】:

  • 我不明白这个问题。你能说清楚一点吗? “但是,我想在不创建 DataBaseRecordInfo 实例的情况下获得这些类型”——这是什么意思?
  • 这意味着我有一些场景,我想要这些变量的类型,但不想实例化这个类来获取类型。

标签: c# enums types typeof


【解决方案1】:

如果您想将枚举值与一些附加信息绑定,您可以使用自己的 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());

【讨论】:

    【解决方案2】:

    这样的事情怎么样:

    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 的实例,但我假设您的意思是静态方法之外的实例。没有人见过这个实例。

    【讨论】:

    • 每次调用该方法时都会创建一个实例。它也不能解决两个地方的维护问题。
    • 我的印象是“在两个地方维护东西”问题仅限于类型,这很好地解决了这些问题。它甚至可以让您灵活地使用不匹配的名称。
    • David,您可以在静态构造函数中创建一个静态实例,以避免在每次调用时创建一个实例。另外,不确定这不是 DRY - 需要解释一下吗?
    • @jsmith - 这是......?它有效,我只是认为这不是解决问题的好方法。
    • @David M 我认为反射是我一直在寻找的。出于设计原因,我宁愿没有默认构造函数,这意味着我将另一个类传递给该类进行解析,因此无法使用默认构造函数声明实例。我当然可以创建一个,但宁愿不创建,看起来很草率。所以是的,它确实有效,但它不是我想要的。
    【解决方案3】:

    如果名称总是完全匹配,您可以使用反射来做到这一点。

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

    您甚至可以将这些值缓存在字典中,因此如果找到,只需返回字典条目,否则确定使用反射并缓存结果。

    【讨论】:

    • +1 我也想过字典的答案,但我更喜欢反射方式
    • 这种混合方法符合所有要求,恕我直言
    • 哈哈,什么?勾选所有方框,我一定错过了什么……甚至在 The New Hacker's Dictionary 中都找不到这个,也许是时候修改一下?
    【解决方案4】:

    是的,您可以使用枚举中的名称以及对 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;
        }
    };
    

    您可能希望将结果缓存在字典中,因为反射在性能方面可能代价高昂。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-30
      相关资源
      最近更新 更多