Dean
Dean

Reputation: 678

Get nested value of constant by name dynamically

I have a class storing constant value like the following below

public class FirstClass
{
    public const string A = "AValue";
    public const string B = "BValue";
    public const string C = "CValue";
}

var name = "A";
Console.WriteLine(typeof(FirstClass).GetField(name).GetValue(null)); //AValue

working pretty good, here the question, once i change the structure to contain nested classes, i did this

public class SecondClass
{
    public class SecondClassOne
    {
        public const string A = "AValue 1";
        public const string B = "BValue 1";
        public const string C = "CValue 1";
    }

    public class SecondClassTwo
    {
        public const string A = "AValue 2";
        public const string B = "BValue 2";
        public const string C = "CValue 2";
    }
}

var className = "SecondClassTwo";
var name = "A";
foreach (Type type in typeof(SecondClass).GetNestedTypes()){
    if(type.Name.Equals(className)){
        Console.WriteLine(type.GetField(name).GetValue(null)); //AValue 2
    }
}

It still working fine, but instead of using for loop to get through all the nested classes, is there any better way to do this? Because the list may get longer and longer, it seems not really great to loop all these listing 1 by 1.

Upvotes: 3

Views: 535

Answers (1)

Jon Skeet
Jon Skeet

Reputation: 1500625

Sure, just use Type.GetNestedType():

var nestedType = typeof(SecondClass).GetNestedType(className);
Console.WriteLine(nestedType.GetField(name).GetValue(null));

However, if you're using this a lot, I'd strongly consider building a dictionary instead - particularly if all your constants are strings. You'd potentially end up with a IReadOnlyDictionary<string, IReadOnlyDictionary<string, string>>:

public IReadOnlyDictionary<string, IDictionary<string, string>> GetConstants() =>
    typeof(SecondClass).GetNestedTypes()
        .ToDictionary(
            type => type.Name,
            (IReadOnlyDictionary<string, string>) 
            type.GetFields().ToDictionary(f => f.Name, (string) f => f.GetValue(null)));

(That's not currently constructing a ReadOnlyDictionary, but you certainly could do that.)

Upvotes: 6

Related Questions