我正在努力创建动态表达式,我有以下场景,我希望有助于实现。
下式给出:
public class planet {
public string name { get;set; }
}
class someTestClass {
[Test]
public void Planet_Exists_Statically(){
var planetName = "earth";
var planets = new List<planet> {new planet {name = planetName}};
var found = planets.Exists(MakePredicate(planetName));
Assert.IsTrue(found);
}
[Test]
public void Planet_Exists_Statically(){
var planetName = "earth";
var planets = new List<planet> {new planet {name = planetName}};
var found = planets.Exists(MakeDynamicPredicate(planetName));
Assert.IsTrue(found);
}
private Predicate<planet> MakePredicate(string planetName){
Expression<Predicate<planet>> pred = p => p.name == planetName;
return pred.Compile();
}
private Predicate<planet> MakeDynamicPredicate(string planetName){
var parm = Expression.Parameter(typeof(planet), "p")
var pred = Expression.Lambda<Predicate<planet>>(
Expression.ReferenceEqual(
Expression.Property(parm, typeof(planet), "name"),
**???WHAT GOES HERE???**,
parm);
return pred.Compile();
}
}
所以我的问题是我无法从MakeDynamicPredicate返回的谓词等于MakePredicate函数生成的谓词。
我读了一个reply post from Jon Skeet,但是不明白如何实现ConstantExpression以便捕获局部变量......
非常感谢任何帮助。
附加信息:前进我可能不知道正在使用的类,因此它最终将被抽象为更通用。
答案 0 :(得分:1)
在您的情况下,您实际上不需要捕获任何局部变量,您只需使用Expression.Constant(planetName)
。
如果您随后使用MakeDynamicPredicate("Pluto")
调用它,则生成的表达式就像您编写p => p.name == "Pluto"
一样。
答案 1 :(得分:1)
正如你可以在Jon的帖子中看到的,你需要一些对象来存储你的变量。对于MakePredicate
,它将由编译器创建,对于MakeDynamicPredicate
,您必须自己完成。首先,我们需要一个用于变量值存储的类。
class someTestClass {
...
private class ValueHolder
{
public string Value;
}
...
}
现在,您将planetName
放入ValueHolder的一个实例中,并创建一个Member Access表达式,以便在谓词表达式中使用它。
private Predicate MakeDynamicPredicate(string planetName){
var valueHolder = new ValueHolder
{
Value = value
};
var valueExpr = Expression.MakeMemberAccess(
Expression.Constant(valueHolder),
valueHolder.GetType().GetField("Value"));
var parm = Expression.Parameter(typeof(planet), "p")
var pred = Expression.Lambda>(
Expression.ReferenceEqual(
Expression.Property(parm, typeof(planet), "name"),
valueExpr,
parm);
}
P.S。查看编译器生成的代码(例如使用ILSpy)以更好地了解各种epxression的创建方式通常是有意义的。