使用反射在C#中识别自定义索引器

31

我有一个带有自定义索引器的类,如下所示

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

如何在 typeof(MyClass).GetProperties() 的结果中识别自定义索引器?

5个回答

43

您还可以使用PropertyInfo.GetIndexParameters方法来查找索引参数,如果返回的项数大于0,则表示它是一个索引属性:

foreach (PropertyInfo pi in typeof(MyClass).GetProperties())
{
    if (pi.GetIndexParameters().Length > 0)
    {
       // Indexed property...
    }
}

4

查找在类型级别定义的DefaultMemberAttribute

(这曾经是IndexerNameAttribute,但他们似乎已经放弃了它)


1
DefaultMemberAttribute 不一定引用索引器,请参见此答案 - Herman
@Herman 如果存在索引器,那么 DefaultMemberAttribute 将会引用它,以至于你不能将 DefaultMemberAttribute 应用于一个带有索引器的类。 - Zev Spitz
@ZevSpitz 有趣的是,如果一个类有多个索引器会发生什么? - Herman
1
@Herman 我猜由于C#中的索引器总是具有名称Item,编译器生成的DefaultMemberAttribute将指向Item,而不指定哪个重载。 - Zev Spitz

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();
    }

1

要获取已知的索引器,您可以使用以下代码:

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

或者,您可以获取索引器的 getter 方法:

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

如果类只有一个索引器,您可以省略类型:
var prop = typeof(MyClass).GetProperty("Item", , BindingFlags.Public | BindingFlags.Instance);

我为那些通过谷歌搜索来到这里的人添加了这个答案。


请注意,只有在C#中索引器才会被命名为“Item”。 - Zev Spitz

1
如果只有一个索引器,您可以使用以下代码:

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

如果有多个索引器,您可以通过像这样提供参数来选择所需的重载版本:
var args = new[] { typeof(int) };
var indexer = typeof(MyClass).GetProperties().First(x => x.GetIndexParameters().Select(y => y.ParameterType).SequenceEqual(args));

您可以创建一个类似这样的助手扩展:

//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));
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接