Voy a publicar un ejemplo completo de cómo usar un indexador:
ParameterExpression dictExpr = Expression.Parameter(typeof(Dictionary<string, int>));
ParameterExpression keyExpr = Expression.Parameter(typeof(string));
ParameterExpression valueExpr = Expression.Parameter(typeof(int));
// Simple and direct. Should normally be enough
// PropertyInfo indexer = dictExpr.Type.GetProperty("Item");
// Alternative, note that we could even look for the type of parameters, if there are indexer overloads.
PropertyInfo indexer = (from p in dictExpr.Type.GetDefaultMembers().OfType<PropertyInfo>()
// This check is probably useless. You can't overload on return value in C#.
where p.PropertyType == typeof(int)
let q = p.GetIndexParameters()
// Here we can search for the exact overload. Length is the number of "parameters" of the indexer, and then we can check for their type.
where q.Length == 1 && q[0].ParameterType == typeof(string)
select p).Single();
IndexExpression indexExpr = Expression.Property(dictExpr, indexer, keyExpr);
BinaryExpression assign = Expression.Assign(indexExpr, valueExpr);
var lambdaSetter = Expression.Lambda<Action<Dictionary<string, int>, string, int>>(assign, dictExpr, keyExpr, valueExpr);
var lambdaGetter = Expression.Lambda<Func<Dictionary<string, int>, string, int>>(indexExpr, dictExpr, keyExpr);
var setter = lambdaSetter.Compile();
var getter = lambdaGetter.Compile();
var dict = new Dictionary<string, int>();
setter(dict, "MyKey", 2);
var value = getter(dict, "MyKey");
para leer desde el indexador la IndexExpression
contiene directamente el valor de la propiedad indexada. Para escribirle, debemos usar Expression.Assign
. Todo lo demás es bastante vanidoso Expression
. Según lo escrito por Daniel, el Indizador normalmente se llama "Artículo". Tenga en cuenta que Expression.Property
tiene una sobrecarga que acepta directamente el nombre del indexador (por lo que "Item"
), pero elegí buscarlo manualmente (para poder reutilizarlo). Incluso he puesto un ejemplo sobre cómo usar LINQ para encontrar la sobrecarga exacta del indexador que desea.
Así como una curiosidad, si nos fijamos en MSDN por ejemplo para Dictionary, bajo Properties encontrará Item
* "normalmente" *, cuando no es así? ¿Cómo podría llegar de manera confiable? –
Se puede cambiar usando el atributo 'IndexerName' en el indexador. Puede reflejar en la clase que contiene el indexador y recuperar el atributo 'DefaultMember' para obtener de manera confiable el nombre de la propiedad del indexador. Consulte [aquí] (http://social.msdn.microsoft.com/Forums/en-US/vstscode/thread/60de101a-278d-4674-bc1a-0a04210d566c) para obtener más información. –
Muchas gracias. Realmente funciona - Expression.Property (parámetro, "Item", Expression.Constant (...)) – Ondra