208

How can I get all constants of any type using reflection?

masoud ramezani
  • 22,228
  • 29
  • 98
  • 151

5 Answers5

361

Though it's an old code:

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

Source

You can easily convert it to cleaner code using generics and 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();
}

Or with one line:

type.GetFields(BindingFlags.Public | BindingFlags.Static |
               BindingFlags.FlattenHierarchy)
    .Where(fi => fi.IsLiteral && !fi.IsInitOnly).ToList();
Christian
  • 9,914
  • 6
  • 45
  • 52
gdoron
  • 147,333
  • 58
  • 291
  • 367
  • 19
    *My +1* was before i even passed 2nd line ..i noticed you're going through every step with its ...intended-by-design purpose... ! this is **SO** important when one needs to learn from it. i wish every one with your experience would do as you did here . – LoneXcoder Dec 10 '12 at 08:49
  • 5
    I'm not sure about the assertions with regards to IsLiteral and IsInitOnly. On testing it would seem that for static readonly properties IsLiteral is always false - so IsLiteral is the only flag you need to check to find constants and you can ignore IsInitOnly. I tried with different field types (e.g. String, Int32) to see if this made any difference but it did not. – Mark Watts May 05 '15 at 09:55
  • 60
    Also, to get the value of the const from the FieldInfo, use GetRawConstantValue(). – Sam Sippe Jul 07 '15 at 00:15
  • 1
    @MarkWatts is right. May be the behaviour changed since this was posted. In any case documentation of `IsLiteral` says `if its value is written at compile time` and that is true only for constants, which is how it is behaving now (tested as of .NET 4.5.2) – nawfal Dec 23 '19 at 07:46
99

If you would like to get the values of all constants of a specific type, from the target type, here is an extension method (extending some of the answers on this page):

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

Then for a class like this

static class MyFruitKeys
{
    public const string Apple = "apple";
    public const string Plum = "plum";
    public const string Peach = "peach";
    public const int WillNotBeIncluded = -1;
}

You can obtain the string constant values like this:

List<string> result = typeof(MyFruitKeys).GetAllPublicConstantValues<string>();
//result[0] == "apple"
//result[1] == "plum"
//result[2] == "peach"
BCA
  • 7,776
  • 3
  • 38
  • 53
  • 3
    Why not this: `.Where(fi => fi.IsLiteral && !fi.IsInitOnly).Select(x => x.GetRawConstantValue()).OfType().ToList();`? – T-moty Oct 26 '18 at 13:08
25

As Type extensions:

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);
    }
}
bytedev
  • 8,252
  • 4
  • 48
  • 56
4

Use property.GetConstantValue() to get value.

Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
Reza Bayat
  • 393
  • 2
  • 5
-2
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();
    }
}

Use: var inputTypeDomain = Constants.InputType.Domain;