C#基于枚举值获取公共变量的类型
我有一个从逗号分隔的文本文件中解析数据的类。我有一个字段枚举,可以帮助我更轻松地解析数据。解析中所有记录的类包含每个字段的公共变量,当然还有它们的变量类型。我需要根据给定的枚举获取这些变量的类型C#基于枚举值获取公共变量的类型,c#,enums,types,typeof,C#,Enums,Types,Typeof,我有一个从逗号分隔的文本文件中解析数据的类。我有一个字段枚举,可以帮助我更轻松地解析数据。解析中所有记录的类包含每个字段的公共变量,当然还有它们的变量类型。我需要根据给定的枚举获取这些变量的类型 public enum DatabaseField : int { NumID1 = 1, NumID2 = 2, NumID3 = 3, }; public class DataBaseRecordInfo {
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类型的反射来获得所需的类型
可以这样做:
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;
}
};
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);
}
}
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());
您可能希望将结果缓存到字典中,因为反射在性能方面可能代价高昂。如果名称总是完全匹配,则可以使用反射来实现这一点
return typeof(DataBaseRecordInfo)
.GetProperty(field.ToString(), BindingFlags.Public | BindingFlags.Instance)
.PropertyType;
您甚至可以将这些值缓存在字典中,因此如果找到,只需返回字典条目,否则确定使用反射并缓存结果。类似这样的内容如何:
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;
}
};
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);
}
}
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());
我知道你说过不必创建
DataBaseRecordInfo
的实例,但我假设你指的是静态方法之外的实例。从来没有人看到过此实例。如果要使用一些附加信息绑定枚举值,可以使用自己的CustomAttribute
也许你需要这样的东西:
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;
}
};
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);
}
}
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());
我不明白这个问题。你能说清楚点吗?“然而,我想在不创建DataBaseRecordInfo实例的情况下获取这些类型”--这意味着什么?这意味着我有一个场景,在其中我想要这些变量的类型,但不想实例化这个类以获取类型。这会在每次调用该方法时创建一个实例。它也不能解决在两个地方维护东西的问题。我得到的印象是,“在两个地方维护东西”的问题仅限于类型,这很好地解决了这一问题。David,你可以在静态构造函数中创建一个静态实例,以避免每次调用都创建一个实例。还有,我不知道这怎么不干——想解释一下吗?@jsmith-哪些是。。。?它是有效的,我只是不认为这是一个很好的解决问题的办法。@David M我认为反思是我一直在寻找的。出于设计原因,我不希望使用默认构造函数,这意味着我将另一个类传递给这个类进行解析,因此不可能使用默认构造函数声明实例。我当然可以创建一个,但我宁愿不创建,因为它看起来很草率。是的,它确实有效,但这不是我想要的。+1我也考虑过字典的答案,但我更喜欢反射法。这种混合方法勾选了所有的框。哈哈,什么?勾选所有的方框,我一定错过了什么。。。在新黑客字典里都找不到这个,也许是时候修改一下了?