【发布时间】:2012-05-02 23:01:50
【问题描述】:
如何使用反射获得任何类型的所有常量?
【问题讨论】:
标签: c# .net reflection constants
如何使用反射获得任何类型的所有常量?
【问题讨论】:
标签: c# .net reflection constants
虽然是旧代码:
private FieldInfo[] GetConstants(System.Type type)
{
ArrayList constants = new ArrayList();
FieldInfo[] fieldInfos = type.GetFields(
// Gets all public and static fields
BindingFlags.Public | BindingFlags.Static |
// This tells it to get the fields from all base types as well
BindingFlags.FlattenHierarchy);
// Go through the list and only pick out the constants
foreach(FieldInfo fi in fieldInfos)
// IsLiteral determines if its value is written at
// compile time and not changeable
// IsInitOnly determines if the field can be set
// in the body of the constructor
// for C# a field which is readonly keyword would have both true
// but a const field would have only IsLiteral equal to true
if(fi.IsLiteral && !fi.IsInitOnly)
constants.Add(fi);
// Return an array of FieldInfos
return (FieldInfo[])constants.ToArray(typeof(FieldInfo));
}
您可以使用泛型和 LINQ 轻松地将其转换为更简洁的代码:
private List<FieldInfo> GetConstants(Type type)
{
FieldInfo[] fieldInfos = type.GetFields(BindingFlags.Public |
BindingFlags.Static | BindingFlags.FlattenHierarchy);
return fieldInfos.Where(fi => fi.IsLiteral && !fi.IsInitOnly).ToList();
}
或者用一行:
type.GetFields(BindingFlags.Public | BindingFlags.Static |
BindingFlags.FlattenHierarchy)
.Where(fi => fi.IsLiteral && !fi.IsInitOnly).ToList();
【讨论】:
IsLiteral 的文档都说if its value is written at compile time,这仅适用于常量,这就是它现在的行为方式(从 .NET 4.5.2 开始测试)
如果您想从目标类型中获取特定类型的所有常量的值,这里有一个扩展方法(扩展本页的一些答案):
public static class TypeUtilities
{
public static List<T> GetAllPublicConstantValues<T>(this Type type)
{
return type
.GetFields(BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy)
.Where(fi => fi.IsLiteral && !fi.IsInitOnly && fi.FieldType == typeof(T))
.Select(x => (T)x.GetRawConstantValue())
.ToList();
}
}
那么对于这样的课程
static class MyFruitKeys
{
public const string Apple = "apple";
public const string Plum = "plum";
public const string Peach = "peach";
public const int WillNotBeIncluded = -1;
}
您可以像这样获取string 常量值:
List<string> result = typeof(MyFruitKeys).GetAllPublicConstantValues<string>();
//result[0] == "apple"
//result[1] == "plum"
//result[2] == "peach"
【讨论】:
.Where(fi => fi.IsLiteral && !fi.IsInitOnly).Select(x => x.GetRawConstantValue()).OfType<T>().ToList();?
作为类型扩展:
public static class TypeExtensions
{
public static IEnumerable<FieldInfo> GetConstants(this Type type)
{
var fieldInfos = type.GetFields(BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy);
return fieldInfos.Where(fi => fi.IsLiteral && !fi.IsInitOnly);
}
public static IEnumerable<T> GetConstantsValues<T>(this Type type) where T : class
{
var fieldInfos = GetConstants(type);
return fieldInfos.Select(fi => fi.GetRawConstantValue() as T);
}
}
【讨论】:
IEnumerable<T> 而不是 IList?
使用property.GetConstantValue() 获取价值。
【讨论】:
GetRawConstantValue()
public class Constants
{
public class InputType
{
public const string DOCUMENTPHOTO = "document-photo";
public const string SELFIEPHOTO = "selfie-photo";
public const string SELFIEVIDEO = "selfie-video";
public static List<string> Domain { get { return typeof(Constants.InputType).GetAllPublicConstantValues<string>(); } }
}
public class Type
{
public const string DRIVINGLICENSE = "driving-license";
public const string NATIONALID = "national-id";
public const string PASSPORT = "passport";
public const string PROOFOFRESIDENCY = "proof-of-residency";
public static List<string> Domain { get { return typeof(Constants.Type).GetAllPublicConstantValues<string>(); } }
}
public class Page
{
public const string FRONT = "front";
public const string BLACK = "back";
public static List<string> Domain { get { return typeof(Constants.Page).GetAllPublicConstantValues<string>(); } }
}
public class FileType
{
public const string FRONT = "selfie";
public const string BLACK = "video";
public const string DOCUMENT = "document";
public const string MEDIA = "media";
public const string CAPTCHA = "captcha";
public const string DIGITALSIGNATURE = "digitalSignature";
public static List<string> Domain { get { return typeof(Constants.FileType).GetAllPublicConstantValues<string>(); } }
}
}
public static class TypeUtilities
{
public static List<T> GetAllPublicConstantValues<T>(this Type type)
{
return type
.GetFields(BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy)
.Where(fi => fi.IsLiteral && !fi.IsInitOnly && fi.FieldType == typeof(T))
.Select(x => (T)x.GetRawConstantValue())
.ToList();
}
}
使用:var inputTypeDomain = Constants.InputType.Domain;
【讨论】: