tags:

views:

74

answers:

2

I've got a struct defined like this

private struct Combinators
{
    public const char DirectChild = '>';
    public const char NextAdjacent = '+';
    public const char NextSiblings = '~';
    public const char Descendant = ' ';
}

I want to use reflection to get a list of all the values of the public const char fields in the struct (as specific as possible). How can I do that?

+7  A: 
var fieldValues = typeof(Combinators)
    .GetFields()
    .Where(x => x.FieldType == typeof(char) && x.IsLiteral)
    .ToDictionary(x => x.Name, x => (char)x.GetValue(null));

Returns a Dictionary<string, char> where the key is the field name, and the value is the field value (as a character).

Update: Added where clause based on comments and @nasufara's suggestion, and added IsLiteral check based on @Jeff M's.

Kirk Woll
Surely you don't mean to pass in `null`? Or is that allowed because their const? You can do better by using `GetFields(BindingFlags.Public)` no? Can you limit it to `char` fields too?
Mark
@Mark, `BindingFlags.Public` is the default, so you don't need to pass it. And you always pass in null for `const` or `static` fields (since the argument refers to an *instance* of which there is none).
Kirk Woll
Inserting a `.Where(x => x.FieldType == typeof(char))` between `.GetFields()` and `.ToDictionary(...)` should limit it to chars.
nasufara
Awesome! Thanks :)
Mark
He wanted constants only too so you'll need to add `x.IsLiteral` to the filter.
Jeff M
@Jeff: Nice! Wasn't sure if that could be done.
Mark
Learnt a bit about reflection from this, thanks :)
Mahesh Velaga
A: 
private class TypedEnum<T> : IEnumerable<T>
{
    public IEnumerator<T> GetEnumerator()
    {
        return GetType().GetFields().Select(f => f.GetValue(null)).OfType<T>().GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}

private class Combinators : TypedEnum<char>
{
    public const char DirectChild = '>';
    public const char NextAdjacent = '+';
    public const char NextSiblings = '~';
    public const char Descendant = ' ';
}

Edit: Blah... there's no way to make a static IEnumerable is there?

Mark