表达式树与字符串赋值和获取价值 [英] Expression Tree with string assignment and getting value

查看:320
本文介绍了表达式树与字符串赋值和获取价值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经建立了自己的SQL查询生成器,打破了一个分开的表达,但是,我有一个问题想获得相同的功能lambda表达式定义字符串的值。



下面是我想在控制台应用程序做的:

 私有静态无效MyBuilderTest()
{
变种sqlBuilder =新SqlBuilder();

//不行的 - 需要指导HERE
VAR testValue =测试; //定义在同一个函数如下

sqlBuilder.Select<拉姆达; FooObject>(O = GT; o.FooValue == testValue);

//作品
变种someObject =新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 + LT;> c__DisplayClass1>(ConsoleApplication1.Program + LT;> c__DisplayClass1 )
的NodeType =常数
类型= {的System.Type} System.RunetimeType
值= {} ConsoleApplication1.Program



Node.Expression.Value包括:

  testValue =测试 (类型:字符串)

我如何得到这个值我?已经试过几件事情,如:

  VAR memberType = node.Expression.Type.DeclaringType; 

这传回一个ConsoleApplication1.Program类型。



然而,当我做的:

  memberType.GetProperty(testValue); //从表达
声明类型



它传回空。



以上方法正常工作,如果我把一个类中的拉姆达弦,但如果他们串在控制台功能定义不起作用。



< ?p>谁能告诉我怎么去的字符串值,如果它在拉姆达的功能级别定义



编辑:新增VisitMember

 保护覆盖表达VisitMember(MemberExpression节点)
{
如果(node.NodeType == ExpressionType.Constant )
{
// Node.Expression是一个常量表达式类型。
// node.Expression包含上面
//性能并具有价值:{} ConsoleApplication1.Program
//在监视窗口展开值显示:testValue =测试

//我如何得到这个值,如果ConsoleApplication1.Program类型没有
//甚至不知道呢?看起来也许动态属性?
}
}



EDITED



添加代码到控制台应用程序例子来说明什么可行,什么不可行。


解决方案

在您的示例中的拉姆达已经关闭了在 testValue 变量,这意味着编译器捕捉到它作为叫同一个名字的在自动生成的类中的字段 ConsoleApplication1.Program + LT;> c__DisplayClass1> 。您可以使用正常的反射通过转换二进制表示的右手侧成的 MemberExpression

  VAR testValue =你好; 
VAR EXPR =(表达式来; Func键<字符串,布尔>>)(X => X == testValue);
VAR RHS =(MemberExpression)((BinaryExpression)expr.Body).Right;
VAR OBJ =((常量表达式)rhs.Expression).value的;
VAR场=(字段信息)rhs.Member;
VAR值= field.GetValue(OBJ);
Debug.Assert的(等于(值,你好));
testValue =改变;
值= field.GetValue(OBJ);
Debug.Assert的(等于(值,改变));



另外,您可以将您的变量变成一个常数。

 常量字符串testValue =你好; 
VAR EXPR =(表达式来; Func键<字符串,布尔>>)(X => X == testValue);
VAR值=((常量表达式)((BinaryExpression)expr.Body).Right).value的;
Debug.Assert的(等于(值,你好));


I have built my own SQL Query builder that breaks apart an Expression, however, I'm having an issue trying to get the value of string defined in the same function as the lambda expression.

Here is what I am trying to do in console app:

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);
}

In my builder it subclasses from ExpressionVisitor, and I override the VisitMember. I found that a string defined in at the base Console level will come back as:

Node.Expression.NodeType == ExpressionType.Constant

The Node.Expression passes back properties of:

CanReduce = false
DebugView = ".Constant<ConsoleApplication1.Program+<>c__DisplayClass1>(ConsoleApplication1.Program+<>c__DisplayClass1)"
NodeType = Constant
Type = System.Type {System.RunetimeType}
Value = {ConsoleApplication1.Program}

The Node.Expression.Value contains:

testValue = "Test" (Type: string)

How do I get this value? I've tried several things, like:

var memberType = node.Expression.Type.DeclaringType;

This passes back a ConsoleApplication1.Program type.

However, when I do:

 memberType.GetProperty("testValue");   // Declaring Type from Expression

It passes back null.

The above methods work fine if I place the lambda "strings" in a class, but doesn't work if they string is defined in the console function.

Can anyone tell me how to get the string value if it's defined at the function level of the lambda?

EDITED: Added 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?
    }
 }

EDITED

Added code to the console app example to show what works and what doesn't.

解决方案

The lambda in your example has "closed over" the testValue variable, meaning the compiler has captured it as a field of the same name in an automatically generated class called ConsoleApplication1.Program+<>c__DisplayClass1>. You can use normal reflection to get the current value of that field by casting the right hand-side of the binary expression into a MemberExpression.

var testValue = "hello";
var expr = (Expression<Func<string, bool>>) (x => x == testValue);
var rhs = (MemberExpression) ((BinaryExpression) expr.Body).Right;
var obj = ((ConstantExpression) rhs.Expression).Value;
var field = (FieldInfo) rhs.Member;
var value = field.GetValue(obj);
Debug.Assert(Equals(value, "hello"));
testValue = "changed";
value = field.GetValue(obj);
Debug.Assert(Equals(value, "changed"));

Alternatively you can change your variable into a constant.

const string testValue = "hello";
var expr = (Expression<Func<string, bool>>) (x => x == testValue);
var value = ((ConstantExpression) ((BinaryExpression) expr.Body).Right).Value;
Debug.Assert(Equals(value, "hello"));

这篇关于表达式树与字符串赋值和获取价值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆