我会发布关于如何使用一个索引一个完整的例子:
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");
要从IndexExpression
直接包含索引属性的值索引读取。要写信给我们,我们必须使用Expression.Assign
。其他一切都相当香草Expression
。正如丹尼尔所写,索引者通常被称为“项目”。请注意,Expression.Property
有一个直接接受索引器名称的过载(所以"Item"
),但我选择手动查找它(以便可以重用)。我甚至举了一个例子来说明如何使用LINQ来找到你想要的索引器的确切超载。
就像一个好奇,如果你看看MSDN例如用于Dictionary,Properties下,你会发现Item
*“通常” *的时候是不是?你怎么能可靠地得到它? –
可以使用索引器上的“IndexerName”属性进行更改。您可以反思包含索引器的类并检索'DefaultMember'属性以可靠地获取索引器属性的名称。请参阅[这里](http://social.msdn.microsoft.com/Forums/en-US/vstscode/thread/60de101a-278d-4674-bc1a-0a04210d566c)了解更多信息。 –
非常感谢。它真的有用 - Expression.Property(参数,“Item”,Expression.Constant(...)) – Ondra