我将发布一个关于如何使用索引器的完整示例:
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。正如 Daniel 所写,索引器通常称为“项目”。请注意,Expression.Property 有一个重载,它直接接受索引器的名称(所以 "Item"),但我选择手动查找它(以便可以重复使用)。我什至举了一个例子,说明如何使用 LINQ 找到你想要的索引器的确切重载。
出于好奇,如果你在 MSDN 上查看 Dictionary,在 Properties 下你会找到 Item