以下のように定義されているインデクサをリフレクションで取得してみましょう。
public object this[int index]
{
get { }
set { }
}
通常のプロパティであれば、以下のようにして取得できます。
( Hoge クラスの Fuga プロパティの場合)
var pi = typeof(Hoge).GetProperty("Fuga", BindingFlags.Public | BindingFlags.Instance)
しかし、インデクサはプロパティ名がないので、上記のように書けません。
と思われますが、このように書くと取得できます。
var pi = typeof(Hoge).GetProperty("Item", BindingFlags.Public | BindingFlags.Instance)
インデクサは内部的に Item と名前で扱われてるんですね。 ※追記あり
試しにこういう定義をしてみましょう。
public class Hoge
{
public object Item { get; set; }
public object this[int indexer] { get; set; }
}
すると'Hoge' は 'Item' の定義を既に含んでいます。
というエラーが発生します。
このことからもインデクサが Item として扱われてることがわかりますね。
追記
@tomochan154 さん、 @chocolamint さんからコメントを頂きました。
まずインデクサを複数定義した場合、上のリフレクションでは例外が発生します。。
また、 IndexerNameAttribute でインデクサの名前を Item 以外に変更する事もできるので、GetProperty("Item", ... と書く方法も適切でないことが分かりました。
お二人から紹介された方法を下に書いておきます。
// this[int index] 一本釣り
var types = new[] { typeof(Int32) };
var pi = typeof(Hoge).GetProperties(BindingFlags.Public | BindingFlags.Instance)
.First(pp => pp.GetIndexParameters().Select(pr => pr.ParameterType).SequenceEqual(types));
// インデクサ全部
var pis = typeof(Hoge).GetProperties(BindingFlags.Public | BindingFlags.Instance)
.Where(p => p.GetIndexParameters().Length > 0).ToArray();
// this[int index] 一本釣り
var types = new[] { typeof(Int32) };
var type = typeof(Hoge);
var pi = type.GetProperty(type.GetCustomAttribute<DefaultMemberAttribute>().MemberName, types);