31

I have a class with a custom indexer like so

public string this[VehicleProperty property]
{
  // Code
}

How can I identify the custom indexer in the results of typeof(MyClass).GetProperties()?

Cœur
  • 37,241
  • 25
  • 195
  • 267
jbenckert
  • 964
  • 1
  • 10
  • 19

5 Answers5

43

You can also look for index parameters, using the the PropertyInfo.GetIndexParameters method, if it returns more than 0 items, it's an indexed property:

foreach (PropertyInfo pi in typeof(MyClass).GetProperties())
{
    if (pi.GetIndexParameters().Length > 0)
    {
       // Indexed property...
    }
}
Bob
  • 5,510
  • 9
  • 48
  • 80
Christian C. Salvadó
  • 807,428
  • 183
  • 922
  • 838
4

Look for the DefaultMemberAttribute defined at type level.

(This used to be IndexerNameAttribute, but they seem to have dropped it)

leppie
  • 115,091
  • 17
  • 196
  • 297
  • 1
    The `DefaultMemberAttribute` does not necessary reference an indexer, see this [answer](https://stackoverflow.com/a/1119949/1161635). – Herman Dec 19 '17 at 10:44
  • @Herman But if there is an indexer, then the `DefaultMemberAttribute` will refer to it, to the extent that you can't apply `DefaultMemberAttribute` to a class with an indexer. – Zev Spitz Jan 03 '19 at 22:50
  • @ZevSpitz Interesting, what happens if the class has more than one indexer? – Herman Jan 03 '19 at 23:44
  • 1
    @Herman I'm guessing since indexers in C# will always have the name `Item`, the compiler-generated `DefaultMemberAttribute` will point to `Item` without specifying which overload. – Zev Spitz Jan 03 '19 at 23:45
3
    static void Main(string[] args) {

        foreach (System.Reflection.PropertyInfo propertyInfo in typeof(System.Collections.ArrayList).GetProperties()) {

            System.Reflection.ParameterInfo[] parameterInfos = propertyInfo.GetIndexParameters();
            // then is indexer property
            if (parameterInfos.Length > 0) {
                System.Console.WriteLine(propertyInfo.Name);
            }
        }


        System.Console.ReadKey();
    }
MaLio
  • 2,498
  • 16
  • 23
1

To get a known indexer you can use:

var prop = typeof(MyClass).GetProperty("Item", new object[]{typeof(VehicleProperty)});
var value = prop.GetValue(classInstance, new object[]{ theVehicle });

or you can get the getter method of the indexer:

var getterMethod = typeof(MyClass).GetMethod("get_Item", new object[]{typeof(VehicleProperty)});
var value = getterMethod.Invoke(classInstance, new object[]{ theVehicle });

if the class has only one indexer, you can omit the type:

var prop = typeof(MyClass).GetProperty("Item", , BindingFlags.Public | BindingFlags.Instance);

I've added this answer for the ones who google search led them here.

Mahmood Dehghan
  • 7,761
  • 5
  • 54
  • 71
1

If there is only one indexer, you can use this:

var indexer = typeof(MyClass).GetProperties().First(x => x.GetIndexParameters().Length > 0));

If there are multiple indexers, you can select the overload you want by supplying the arguments like this:

var args = new[] { typeof(int) };
var indexer = typeof(MyClass).GetProperties().First(x => x.GetIndexParameters().Select(y => y.ParameterType).SequenceEqual(args));

You can create a helper extension like this:

//Usage      
var indexer = typeof(MyClass).GetIndexer(typeof(VehicleProperty));
//Class
public static class TypeExtensions
{
  public static PropertyInfo GetIndexer(this Type type, params Type[] arguments) => type.GetProperties().First(x => x.GetIndexParameters().Select(y => y.ParameterType).SequenceEqual(arguments));
}
Robear
  • 986
  • 1
  • 11
  • 15