【发布时间】:2013-01-11 09:28:33
【问题描述】:
我已经构建了自己的 SQL 查询构建器来分解表达式,但是,我在尝试获取与 lambda 表达式相同的函数中定义的字符串值时遇到了问题。
这是我在控制台应用程序中尝试做的事情:
private static void MyBuilderTest()
{
var sqlBuilder = new SqlBuilder();
// Doesn't work -- NEED GUIDANCE HERE
var testValue = "Test"; // Defined in the same function as the lambda below
sqlBuilder.Select<FooObject>(o => o.FooValue == testValue);
// Works
var someObject = new SomeObject { SomeValue = "classTest };
sqlBuilder.Select<FooObject>(o => o.FooValue == someObject.SomeValue);
}
在我的构建器中,它是 ExpressionVisitor 的子类,我覆盖了 VisitMember。我发现在基本控制台级别定义的字符串将返回为:
Node.Expression.NodeType == ExpressionType.Constant
Node.Expression 传回以下属性:
CanReduce = false
DebugView = ".Constant<ConsoleApplication1.Program+<>c__DisplayClass1>(ConsoleApplication1.Program+<>c__DisplayClass1)"
NodeType = Constant
Type = System.Type {System.RunetimeType}
Value = {ConsoleApplication1.Program}
Node.Expression.Value 包含:
testValue = "Test" (Type: string)
我如何获得这个值?我已经尝试了几件事,例如:
var memberType = node.Expression.Type.DeclaringType;
这会传回一个 ConsoleApplication1.Program 类型。
但是,当我这样做时:
memberType.GetProperty("testValue"); // Declaring Type from Expression
它传回 null。
如果我将 lambda“字符串”放在一个类中,上述方法可以正常工作,但如果它们的字符串是在控制台函数中定义的,则不起作用。
如果字符串值是在 lambda 的函数级别定义的,谁能告诉我如何获取字符串值?
已编辑:添加了 VisitMember
protected override Expression VisitMember(MemberExpression node)
{
if (node.NodeType == ExpressionType.Constant)
{
// Node.Expression is a ConstantExpression type.
// node.Expression contains properties above
// And Has Value of: {ConsoleApplication1.Program}
// Expanding Value in Watch window shows: testValue = "Test"
// How do I get this value, if the ConsoleApplication1.Program type doesn't
// even know about it? Looks like maybe a dynamic property?
}
}
已编辑
向控制台应用程序示例添加了代码,以显示哪些有效,哪些无效。
【问题讨论】:
-
我认为你做错了。您应该尝试找到
ConstantExpression并从中获取价值。我建议不要像你一样使用反射,因为那是一种重新发明轮子(如果你询问表达式而不是字段/属性,当然没有任何帮助)。但是,为了提供更多帮助,您能否提供有关您的构建器代码的更多上下文 - 它在哪里得到node等? -
"node" 在 VisitMember 的覆盖中传入,是 MemberExpression 类型。
-
所以更多地询问那个节点——它是一个树,其中一个子节点将是
ConstantExpression的一个实例,它有一个Value类型的属性object将包含文字testValue。 (实际上,您正在关闭一个变量,因此它可能是编译器生成的类型;可能您甚至需要GetField代替——如果编译器生成带有字段或属性的类,我会忘记) -
这就是重点。我可以看到带有 testValue = test 的值(在调试期间的 Watch 窗口中),但我如何获得它?如果对象是“对象”类型并且不知道“testValue”属性,我如何获取此值。 Node.Expression.Value 位于树的底部,所以我所做的任何事情都会传回 {ConsoleApplication3.Program}。
标签: c# linq expression-trees