【发布时间】:2017-03-01 11:59:39
【问题描述】:
我创建了三个类。
两个类Data 和IntArrayEqualityComparer 在下面-
public class Data
{
public Dictionary<int[], List<double>> s = new Dictionary<int[], List<double>>(new IntArrayEqualityComparer());
public Data()
{
}
public Data(Dictionary<int[], List<double>> s)
{
this.s = s;
}
public Dictionary<int[], List<double>> S
{
get { return s; }
set { s = value; }
}
}
public class IntArrayEqualityComparer : IEqualityComparer<int[]>
{
public bool Equals(int[] x, int[] y)
{
if (x.Length != y.Length)
{
return false;
}
for (int i = 0; i < x.Length; i++)
{
if (x[i] != y[i])
{
return false;
}
}
return true;
}
public int GetHashCode(int[] obj)
{
int result = 17;
for (int i = 0; i < obj.Length; i++)
{
unchecked
{
result = result * 23 + obj[i];
}
}
return result;
}
}
创建了名为Expression 的第三个类,我需要在其中将 LINQ 表达式转换为反射 -
public class Expresion
{
public void CreateExpression()
{
Expression<Func<Data, List<int>>> exp1 = null;
//Below is the LINQ expression I want to convert
exp1 = p2 => p2.s[new int[] { 14, 5 }].Select((item, index) => new { item, index }).Select(x => x.index).ToList();
ParameterExpression p1 = Expression.Parameter(typeof(Data), "p");
MethodInfo mInfo = typeof(List<double>).GetMethod("get_Item");
MethodInfo mInfo1 = typeof(Dictionary<int, List<double>>).GetMethod("get_Item");
MethodInfo mInfo2 = typeof(Dictionary<int[], List<double>>).GetMethod("get_Item");
MethodInfo mInfo3 = typeof(List<int[]>).GetMethod("get_Item");
MemberExpression s1 = Expression.Property(p1, "s");
ParameterExpression index1 = Expression.Parameter(typeof(int), "index");
ParameterExpression item1 = Expression.Parameter(typeof(double), "item");
//Here I want to covert the "(item, index) => new { item, index }" part from LINQ expression into Reflection
}
}
【问题讨论】:
-
我不会依赖
"get_Item"作为MethodInfo对象,您可能应该通过查找GetIndexParameters具有计数的索引器来找到索引器PropertyInfo。但这只是我。要执行您想要的操作,您必须使用适当的重载从 Enumerable.Select 创建泛型方法调用,创建一个 lambda 表达式(通知您的匿名类型)并将其传递给它。问题将是构建您的匿名类型,可以在此处看到一个示例:stackoverflow.com/a/3740637/491907 -
顺便说一句,专业提示:编写
Expression<Func<... >> exp = p2 =>....并在其后设置断点。然后使用调试器检查exp的DebugView“属性”,看看它是如何构造的。在这种情况下它可能不起作用,但它肯定会有所帮助。您还可以安装其他更易于阅读的表达式可视化。 -
你可能把事情复杂化了。如果您所做的只是选择索引,您实际上并不需要匿名类型。您可以删除第二个链接的
Select,然后将索引作为 int 返回第一个。 -
从技术上讲,您不能完全在运行时创建此表达式...您需要在某处使用匿名类型
new { item, index },以便编译器创建它。
标签: c# linq expression-trees