In C# Getting the Constant Value from Class using Reflection need not be a difficult and there are quite few articles and blogs written on the subject. I wanted to mimic the GetNameQuery function that is in Hibernate, maintaining backward compatibility while converting services to C# using Dapper. For Inspiration I looked at this blog. This returned a list of the constant Names and what I actually wanted to do was look through all the constant names and then match mine and return the Sql value inside.

Where to start: reflection

Firstly we need to look at the FieldInfo Class looking at the example it shows us how we can get the field values.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
using System;
using System.Reflection;
 
public class FieldInfoClass
{
    public int myField1 = 0;
    protected string myField2 = null;
    public static void Main()
    {
        FieldInfo[] myFieldInfo;
        Type myType = typeof(FieldInfoClass);
        // Get the type and fields of FieldInfoClass.
        myFieldInfo = myType.GetFields(BindingFlags.NonPublic | BindingFlags.Instance
            | BindingFlags.Public);
        Console.WriteLine("\nThe fields of " + 
            "FieldInfoClass are \n");
        // Display the field information of FieldInfoClass.
        for(int i = 0; i < myFieldInfo.Length; i++)
        {
            Console.WriteLine("\nName            : {0}", myFieldInfo[i].Name);
            Console.WriteLine("Declaring Type  : {0}", myFieldInfo[i].DeclaringType);
            Console.WriteLine("IsPublic        : {0}", myFieldInfo[i].IsPublic);
            Console.WriteLine("MemberType      : {0}", myFieldInfo[i].MemberType);
            Console.WriteLine("FieldType       : {0}", myFieldInfo[i].FieldType);
            Console.WriteLine("IsFamily        : {0}", myFieldInfo[i].IsFamily);
        }
    }
}

Getting constant names

What is missing in the example is BindingFlags.FlattenHierarchy. BindingFlags Specifies flags that control the binding and the way in which we search for members and types by reflection. FlattenHierarchy specifies that public and protected static members up the hierarchy should be returned. From this we can get an array of FieldInfo objects. This is the first step, and for our purposes we can simplify it as we are only after public static values, this will contain the fieldInfo.Name property which is what we need for comparison purposes.

1
FieldInfo[] fields = type.GetFields(BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy);

Getting constant value

Somewhere while browsing all the examples there was much ado about getting the constants as a list using Linq, I wanted the values this becomes rather easy and can be done as a one liner. For readability I decided to keep it apart in my code because heaven forbid I forget what I wrote at the time. Now we return a list of all Values using the GetRawConstantValuemethod, but by adding an filter we can get to the exact item we are after fieldInfo.Name.Equals(name). Now now our code looks a little different, this returns one list item

1
2
3
t = (fields.Where(fieldInfo => fieldInfo.IsLiteral
	&& !fieldInfo.IsInitOnly && fieldInfo.Name.Equals(name)
	&& fieldInfo.FieldType == typeof(T)).Select(f => (T)f.GetRawConstantValue())).ToList();

Making it work for us

We still need to take this one step further and return our constants value. I found that it worked easiest and by specifying first and then converting it to type string. Otherwise you will end up with a system type and an error.

1
2
3
t = (fields.Where(fieldInfo => fieldInfo.IsLiteral
	&& !fieldInfo.IsInitOnly && fieldInfo.Name.Equals(name)
	&& fieldInfo.FieldType == typeof(T)).Select(f => (T)f.GetRawConstantValue())).ToList().First().ToString();

In conclusion

So let’s put it all together.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public string GetNamedQuery(string namedQuery)
{
	return GetConstantValue<string>(typeof(YourClass), namedQuery);
}
 
private string GetConstantValue<t>(Type type, string name)
{
FieldInfo[] fields = type.GetFields(BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy);
string t;
try
{
	t = (fields.Where(fieldInfo => fieldInfo.IsLiteral
		&& !fieldInfo.IsInitOnly && fieldInfo.Name.Equals(name)
		&& fieldInfo.FieldType == typeof(T)).Select(f => (T)f.GetRawConstantValue())).ToList().First().ToString();
}
catch (Exception)
	{
		throw new IntegrationServiceException("YourApp.Service.main.GetEntityList", new SystemException("Named Query does not exist")); 
	}
	return t;
}
</t></string>

So there you have it a simple, generic, robust and searchable way of getting the value of all string constants in a class.you could obviously simplify this but it’s really clean and readble and I like it.

Leave a Reply

You must be logged in to post a comment.