标签: expression-trees

构建LINQ表达式树:如何在范围内获取变量

我正在构建一个LINQ表达式树,但它不会编译,因为据称局部变量$var1超出了范围:

变量''类型'System.Object'从范围''引用,但它没有定义

这是表达式树:

.Block() {
    $var1;
    .If ($n.Property1 == null) {
        .Block() {
            $var1 = null;
            .Return #Label1 { }
        }
    } .Else {
        .Default(System.Void)
    };
    $var1 = (System.Object)($n.Property1).Length;
    .Label
    .LabelTarget #Label1:;
    $var1
}
Run Code Online (Sandbox Code Playgroud)

以下代码负责构建树.它是更大的东西的一部分,因此我不希望它的目的从这个例子中完全清楚.

MemberExpression sourceExpression = ...;

List<Expression> expressions = new List<Expression>();
LabelTarget returnTarget = Expression.Label();
ParameterExpression resultVariable = Expression.Variable(typeof(object));

expressions.Add(resultVariable);

expressions.Add(
    Expression.IfThen(
        Expression.Equal(sourceExpression, Expression.Constant(null)),
        Expression.Block(
            Expression.Assign(resultVariable, Expression.Constant(null)),
            Expression.Return(returnTarget))));

expressions.Add(
    Expression.Assign(
        resultVariable,
        Expression.Convert(sourceExpression, typeof(object))));

expressions.Add(Expression.Label(returnTarget));
expressions.Add(resultVariable);

Expression finalExpression = Expression.Block(expressions);
object result = Expression.Lambda<Func<object>>(finalExpression).Compile()();
Run Code Online (Sandbox Code Playgroud)

所以问题是:如何将局部变量放入范围,以便表达式成功编译?

.net c# linq lambda expression-trees

27
推荐指数
1
解决办法
1万
查看次数

LINQ表达树是否适合树木?

LINQ表达树是否适当的树,如图,(有针对性或不指向,维基百科似乎不太一致)没有循环?以下C#表达式中表达式树的根是什么?

(string s) => s.Length
Run Code Online (Sandbox Code Playgroud)

表达式树看起来像这样," - >"表示可通过其他节点访问的节点的属性名称.

     ->Parameters[0]
 Lambda---------Parameter(string s)
    \               /
     \->Body       /->Expression
      \           /
      Member(Length)
Run Code Online (Sandbox Code Playgroud)

使用ExpressionVisitor访问LambdaExpression时,将访问ParameterExpression两次.有没有办法使用ExpressionVisitor访问LambdaExpression,以便所有节点只访问一次,并以特定的,众所周知的顺序(预订,有序,后订单等)?

c# linq expression-trees

27
推荐指数
2
解决办法
861
查看次数

变量''类型''引用范围'',但它没有定义

那么,以下代码是自我解释的; 我想将两个表达式合并为一个使用And运算符.最后一行导致符文时间错误:

附加信息:从范围''引用的'System.String'类型的变量'y',但未定义

码:

Expression<Func<string, bool>> e1 = y => y.Length < 100;
Expression<Func<string, bool>> e2 = y => y.Length < 200;

var e3 = Expression.And(e1.Body, e2.Body);

var e4 = Expression.Lambda<Func<string, bool>>(e3, e1.Parameters.ToArray());
e4.Compile(); // <--- causes run-time error
Run Code Online (Sandbox Code Playgroud)

c# expression-trees

27
推荐指数
3
解决办法
2万
查看次数

如何从()=> foo.Title表达式获取对象实例

我有一个带有属性的简单类

class Foo 
{ 
    string Title { get; set; } 
}
Run Code Online (Sandbox Code Playgroud)

我试图通过调用函数来简化数据绑定

BindToText(titleTextBox, ()=>foo.Title );
Run Code Online (Sandbox Code Playgroud)

这被宣称为

void BindToText<T>(Control control, Expression<Func<T>> property)
{
    var mex = property.Body as MemberExpression;
    string name = mex.Member.Name;

    control.DataBindings.Add("Text", ??? , name);
}
Run Code Online (Sandbox Code Playgroud)

那么我应该???为我的Foo班级实例投入什么呢.如何foo从lambda表达式中获取对调用实例的引用?

编辑: 实例应该在某处,因为我可以调用property.Compile()并创建一个使用foo我的BindToText函数中的实例的委托.所以我的问题是,如果可以在不添加函数参数中实例的引用的情况下完成此操作.我呼吁Occum的Razor提供最简单的解决方案.

编辑2: 许多人没有注意到的是在我的函数内部访问实例时存在的闭包foo,如果我编译lambda.为什么编译器知道在哪里找到实例,我不知道?我坚持认为必须有一个答案,不必通过额外的论证.


感谢VirtualBlackFox解决方案是这样的:

void BindText<T>(TextBoxBase text, Expression<Func<T>> property)
{
    var mex = property.Body as MemberExpression;
    string name = …
Run Code Online (Sandbox Code Playgroud)

c# data-binding lambda expression-trees .net-3.5

26
推荐指数
1
解决办法
5820
查看次数

是否有一个特殊的原因LinqKit的扩展器无法从字段中获取表达式?

我正在使用LinqKit库,它允许动态组合表达式.

这是编写Entity Framewok数据访问层的纯粹幸福,因为可以选择重复使用和组合多个表达式,这样就可以实现可读和高效的代码.

请考虑以下代码:

private static readonly Expression<Func<Message, int, MessageView>> _selectMessageViewExpr =
    ( Message msg, int requestingUserId ) =>
        new MessageView
        {
            MessageID = msg.ID,
            RequestingUserID = requestingUserId,
            Body = ( msg.RootMessage == null ) ? msg.Body : msg.RootMessage.Body,
            Title = ( ( msg.RootMessage == null ) ? msg.Title : msg.RootMessage.Title ) ?? string.Empty
        };
Run Code Online (Sandbox Code Playgroud)

我们声明了一个投射Message到的表达式MessageView(为了清楚起见,我删除了细节).

现在,数据访问代码可以使用此表达式来获取单个消息:

var query = CompiledQueryCache.Instance.GetCompiledQuery(
    "GetMessageView",
    () => CompiledQuery.Compile(
        _getMessagesExpr
            .Select( msg => _selectMessageViewExpr.Invoke( msg, userId ) ) …
Run Code Online (Sandbox Code Playgroud)

c# lambda closures expression-trees linqkit

26
推荐指数
2
解决办法
4463
查看次数

C#编译器错误?用于Expression中的只写属性的对象初始化程序语法使csc崩溃

您可能会认为这是一个错误报告,但是我很好奇我是否在这里非常错误,或者是否有来自Eric或Microsoft的其他人的解释.

更新

现在,这是作为 Microsoft Connect上的错误发布的.

描述

考虑以下课程:

class A 
{
    public object B {
        set { }
    }
}
Run Code Online (Sandbox Code Playgroud)

这里A.B是一个只写但其他方面很好的属性.
现在,想象一下我们在表达式中分配它:

Expression<Func<A>> expr = 
    () => new A {
        B = new object { }
    };
Run Code Online (Sandbox Code Playgroud)

此代码使C#编译器(3.5 .30729.4926和4.0 .30319.1)吐出

内部编译器错误(地址013E213F处的0xc0000005):可能的罪魁祸首是"BIND".

和崩溃.

但是,{ }使用构造函数(( ))替换对象初始化程序语法()就可以了.

完整的复制代码:

using System;
using System.Linq.Expressions;

class Test {
    public static void Main()
    {
        Expression<Func<A>> expr = 
            () => new …
Run Code Online (Sandbox Code Playgroud)

c# compiler-construction expression-trees writeonly compiler-bug

26
推荐指数
1
解决办法
891
查看次数

如何设置值属性选择器Expression <Func <T,TResult >>

我需要使用模式工厂的想法将我的Person类实体中的实体属性Address与我的FactoryEntities类中的表达式linq相关联,看看这就是我拥有的和我想做的事情:

Address address = new Address();
address.Country = "Chile";
address.City = "Santiago";
address.ZipCode = "43532";
//Factory instance creation object
//This is idea
Person person = new FactoryEntity<Person>().AssociateWithEntity(p=>p.Address, address);

public class Person: Entity
{
    public string Name{ get; set; }
    public string LastName{ get; set; }
    public Address Address{ get; set; }
}

public class Address: Entity
{
    public string Country{ get; set; }
    public string City{ get; set; }
    public string ZipCode{ get; set; }
}

public class FactoryEntity<TEntity> where …
Run Code Online (Sandbox Code Playgroud)

c# linq expression-trees

25
推荐指数
2
解决办法
2万
查看次数

如何在执行之前将Entity Framework包装起来拦截LINQ表达式?

我想在执行之前重写LINQ表达式的某些部分.而且我在将重写器注入正确的位置时遇到了问题(实际上是这样).

查看实体框架源(在反射器中)它最终归结为IQueryProvider.ExecuteEF中的哪一个通过ObjectContext提供internal IQueryProvider Provider { get; }属性与表达式耦合.

所以我创建了一个包装器类(实现IQueryProvider),在调用Execute时执行Expression重写,然后将其传递给原始的Provider.

问题是,背后的领域Providerprivate ObjectQueryProvider _queryProvider;.这ObjectQueryProvider 是一个内部密封类,这意味着不可能创建一个提供添加重写的子类.

因此,由于非常紧密耦合的ObjectContext,这种方法让我陷入了死胡同.

如何解决这个问题呢?我看错了方向吗?有没有办法让自己注意到这个ObjectQueryProvider

更新:虽然提供的解决方案在您使用存储库模式"包装"ObjectContext时都能正常工作,但是允许直接使用ObjectContext生成的子类的解决方案将更可取.因此保持与Dynamic Data脚手架兼容.

c# linq entity-framework expression-trees

24
推荐指数
2
解决办法
1万
查看次数

为什么从Expression <Func <>>创建的Func <>比直接声明的Func <>慢?

为什么Func<>Expression<Func<>>via .Compile()创建的文件比直接使用Func<>声明要慢得多?

我刚刚使用Func<IInterface, object>声明直接更改为Expression<Func<IInterface, object>>在我正在处理的应用程序中创建的一个,我注意到性能下降了.

我刚做了一点测试,Func<>从一个Expression创建的"几乎"是Func<>直接声明的时间的两倍.

在我的机器上,Direct Func<>大约需要7.5秒,Expression<Func<>>大约需要12.6秒.

这是我使用的测试代码(运行Net 4.0)

// Direct
Func<int, Foo> test1 = x => new Foo(x * 2);

int counter1 = 0;

Stopwatch s1 = new Stopwatch();
s1.Start();
for (int i = 0; i < 300000000; i++)
{
 counter1 += test1(i).Value;
}
s1.Stop();
var result1 = s1.Elapsed;



// Expression . Compile()
Expression<Func<int, Foo>> expression = x => new Foo(x …
Run Code Online (Sandbox Code Playgroud)

c# delegates expression func expression-trees

24
推荐指数
2
解决办法
4619
查看次数

如何使用多个条件构建Lambda表达式树

注意:我知道使用动态linq创建它很简单,但我想学习.

我想创建一个"找到"的lambda:Name = David AND Age = 10.

 class Person
    {
       public int Age { get; set; }
       public string Name { get; set; }
    }

    var lambda = LabmdaExpression<Person>("Name", "David", "Age", 10);

static Expression<Func<T, bool>> LabmdaExpression<T>(string property1, string value1, string property2, int value2)
{

     ParameterExpression parameterExpression = Expression.Parameter(typeof(Person), "o");
     MemberExpression memberExpression1 = Expression.PropertyOrField(parameterExpression, property1);
     MemberExpression memberExpression2 = Expression.PropertyOrField(parameterExpression, property2);

     ConstantExpression valueExpression1 = Expression.Constant(value1, typeof(string));
     ConstantExpression valueExpression2 = Expression.Constant(value2, typeof(int));

     BinaryExpression binaryExpression1 = Expression.Equal(memberExpression1, valueExpression1);
     BinaryExpression binaryExpression2 = Expression.Equal(memberExpression2, valueExpression2); …
Run Code Online (Sandbox Code Playgroud)

c# linq lambda expression-trees

24
推荐指数
1
解决办法
1万
查看次数