Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 带字符串赋值和获取值的表达式树_C#_Linq_Expression Trees - Fatal编程技术网

C# 带字符串赋值和获取值的表达式树

C# 带字符串赋值和获取值的表达式树,c#,linq,expression-trees,C#,Linq,Expression Trees,我已经构建了自己的SQL查询生成器来分解表达式,但是,在尝试获取与lambda表达式相同的函数中定义的字符串值时遇到了问题 以下是我在console应用程序中尝试执行的操作: private static void MyBuilderTest() { var sqlBuilder = new SqlBuilder(); // Doesn't work -- NEED GUIDANCE HERE var testValue = "Test"; // Defined in

我已经构建了自己的SQL查询生成器来分解表达式,但是,在尝试获取与lambda表达式相同的函数中定义的字符串值时遇到了问题

以下是我在console应用程序中尝试执行的操作:

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);
}
Node.Expression传回以下内容的属性:

CanReduce = false
DebugView = ".Constant<ConsoleApplication1.Program+<>c__DisplayClass1>(ConsoleApplication1.Program+<>c__DisplayClass1)"
NodeType = Constant
Type = System.Type {System.RunetimeType}
Value = {ConsoleApplication1.Program}
如何获得该值?我已经尝试了几种方法,例如:

var memberType = node.Expression.Type.DeclaringType;
这将传回一个ConsoleApplication1.Program类型

然而,当我这样做时:

 memberType.GetProperty("testValue");   // Declaring Type from Expression
它返回空值

如果我把lambda“strings”放在一个类中,上面的方法可以很好地工作,但是如果它们的string是在控制台函数中定义的,那么就不能工作

如果字符串是在lambda的函数级别定义的,有人能告诉我如何获取它吗

编辑:添加访问成员

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?
    }
 }
已编辑


向console应用程序示例中添加了代码,以显示哪些有效,哪些无效。

示例中的lambda已“关闭”了
testValue
变量,这意味着编译器已将其捕获为自动生成的名为
ConsoleApplication1.Program+c\u DisplayClass1>类中的同名字段。
。您可以使用法线反射,通过将二进制表达式的右侧强制转换为文本来获取该字段的当前值

var testValue=“hello”;
var expr=(表达式)(x=>x==testValue);
var rhs=(MemberExpression)((BinaryExpression)expr.Body);
var obj=((ConstantExpression)rhs.Expression).Value;
变量字段=(FieldInfo)rhs.Member;
var值=字段。获取值(obj);
Assert(等于(值,“hello”);
testValue=“已更改”;
值=字段。获取值(obj);
Assert(等于(值,“已更改”);
或者,您可以将变量更改为常量

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"));
const string testValue=“hello”;
var expr=(表达式)(x=>x==testValue);
var值=((ConstantExpression)((二进制表达式)expr.Body).Right.value;
Assert(等于(值,“hello”);

与其自己做这件事,不如看一看。它将所有对常量的引用都替换为常量本身。

我认为您的做法是错误的。您应该尝试查找
ConstantExpression
并从中获取值。我建议不要在进行操作时使用反射,因为这有点像是在重新发明轮子(当然,如果您是在组织表达式而不是字段/属性,则毫无帮助)。但是,为了提供更多帮助,您能否提供构建器代码周围的更多上下文—它从哪里获得
节点
,等等?“节点”在VisitMember的覆盖中传递,是一个MemberExpression类型。因此,请进一步询问该节点—它是一个树,其中一个子节点将是
ConstantExpression
的实例,具有类型为
object
Value
属性,该属性将包含文本
testValue
。(实际上,您正在关闭一个变量,因此它可能是编译器生成的类型;您甚至可能需要
GetField
——我不知道编译器是否生成具有字段或属性的类)这就是重点。我可以通过testValue=test(在调试期间的监视窗口中)看到值,但是如何获得它呢?如果对象是“对象”类型并且不知道“testValue”属性,那么如何获取该值。Node.Expression.Value位于树的底部,因此我所做的任何事情都会返回{ConsoleApplication3.Program}。
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?
    }
 }
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"));
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"));