Вы можете сделать это с отражением.
Ниже приведен пример доступа к классу с двумя индексаторами с разными типами ключей, если вы всегда уверены, какой тип индексатора у вас есть, это будет немногоменее сложныйНо я думаю, что стоит отметить, что возможен класс с несколькими индексаторами или индексатор с несколькими ключами.
public class IndexedClass
{
public string SomeProperty { get; set; }
public int[] SomeArray { get; set; } = new int[] { 3, 4, 5 };
Hashtable _items = new Hashtable();
public object this[object key]
{
get
{
Console.WriteLine("object key");
return _items[key];
}
set
{
_items[key] = value;
}
}
public object this[int key]
{
get
{
Console.WriteLine("int key");
return _items[key];
}
set
{
_items[key] = value;
}
}
}
обычный доступ к индексатору:
IndexedClass ic = new IndexedClass();
ic["some string"] = "some string value";
Console.WriteLine(ic["some string"]);
ic[1] = 10;
Console.WriteLine(ic[1]);
Console.WriteLine(ic[2]==null);
выбор и доступ к правильномуиндексатор через отражение:
object index = 1;
object myIndexedObject = ic;
Type myIndexType = index.GetType();
var myIndexerProperty = myIndexedObject.GetType().GetProperties().FirstOrDefault(a =>
{
var p = a.GetIndexParameters();
// this will choose the indexer with 1 key
// <<public object this[int key]>>,
// - of the EXACT type:
return p.Length == 1
&& p.FirstOrDefault(b => b.ParameterType == myIndexType) != null;
// notice that if you call the code below instead,
// then the <<public object this[object key]>> indexer
// will be chosen instead, as it is first in the class,
// and an <<int>> is an <<object>>
//return p.Length == 1
// && p.FirstOrDefault(b => b.ParameterType.IsAssignableFrom(myIndexType)) != null;
});
if (myIndexerProperty != null)
{
object myValue = myIndexerProperty
.GetValue(myIndexedObject, new object[] { index });
Console.WriteLine(myValue);
}
Если у вас всегда есть только один индексатор с одним ключом, вы можете сделать это вместо этого, чтобы получить свой индексатор, так как имя свойства индексатора по умолчанию равно "Item"
:
var myIndexerProperty = myIndexedObject.GetType().GetProperty("Item");
Обратите внимание, что теоретически могут существовать классы со свойством Item
, которое не является индексатором, поэтому вам следует проверить, если myIndexerProperty.GetIndexParameters().Length == 1
в любом случае.