C# 带字符串赋值和获取值的表达式树
我已经构建了自己的SQL查询生成器来分解表达式,但是,在尝试获取与lambda表达式相同的函数中定义的字符串值时遇到了问题 以下是我在console应用程序中尝试执行的操作: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
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"));