1

System.Reflection.PropertyInfo and System.Reflection.ParameterInfo don't seem to expose any way to get the values used at runtime to access indexed property values. If correct, this means that one must know the index values (i.e. keys) in advance - unlike a dictionary, there is no .Keys or similar construct to give access to those index values.

My goal is to be able to take an indexed property accessible via a string key and use its keys and values to construct a new dictionary. Is there any way to do this?

Ben Reich
  • 16,222
  • 2
  • 38
  • 59
Iucounu
  • 1,630
  • 1
  • 20
  • 31

3 Answers3

2

Unfortunately, this is not possible, unless the class "cooperates". Since the only difference between an indexer and any other method is that indexer offers a special syntax, iterating over all keys is generally not possible for the same reasons why it is not possible to go through all values returned by a function.

Consider someone writing an "indexer" that takes a string, and returns its reversed value. In C# this would be a valid indexer; however, it would be unusable for the purposes of enumerating all its possible values.

However, classes that expose indexers often implement IEnumerable<...>. For example, IDictionary<K,V> exposes IEnumerable<KeyValuePair<K,V>>, which lets you enumerate keys along with their corresponding values. Of course classes do not have to do it, but when they do, your code can exploit that to construct whatever output that you need.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • Thank you. It appears that my only recourse is to iterate through all possible strings... will have to test the performance impact. – Iucounu Jun 25 '13 at 14:31
  • @Iucounu The set of "all possible strings" becomes too large very quickly, even when you have limit of just 10..15 UNICODE-16 characters. – Sergey Kalinichenko Jun 25 '13 at 14:33
1

No, there's no way of doing this - because it doesn't make sense to do so.

Like properties, indexers are just methods with some extra metadata. So this:

public int this[int x, int y]
{
    get { return x * y; } 
}

Is just like this:

public int ComputeValue(int x, int y)
{
    return x * y;
}

If the indexer has a setter, that's just another method with an extra parameter as the value being set.

Look at the indexer above - what would you say the "indexed property values" are? It can work with any int values. That's certainly not a typical indexer, but it's entirely valid from a language perspective.

If you're writing an indexer which only accepts some inputs, you can choose to expose that (just as Dictionary<,> exposes a Keys property) but it's up to you to do so.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Thank you. It appears that my only recourse is to iterate through all possible strings... will have to test the performance impact. – Iucounu Jun 25 '13 at 14:31
  • Well what does "all possible strings" mean in this case? If you could provide more context, we may be able to give more advice. Fundamentally, an indexer *could* accept any string... – Jon Skeet Jun 25 '13 at 14:36
0

There's "no keys" because you hid them inside the getter. What the keys are depends on your implementation for instance you could have a private member of type dictionary and then wrapped it up in a class.

so you could do myClass["SomeKey"] instead of myClass.Values["SomeKey"]

ie you are hiding how Values is implemented in this example by Dictionary<String,int> perhaps.

So you need to add a method to expose the keys to your class, course the bonus ball is you might not need reflection at all.

Tony Hopkinson
  • 20,172
  • 3
  • 31
  • 39