为List.Any子句

时间:2015-07-13 23:17:24

标签: c# lambda expression-trees

考虑这种类的层次结构。

class Event
{
    public Attendees[] AttendeesList;
}

class Attendees
{
    public ComplexProperty Property;
    public object Value;
}

class ComplexProperty
{

}

class Program
{
    static void Main(string[] args)
    {
        // There are constants.
        ComplexProperty constproperty = new ComplexProperty();
        object constValue = 5;

        // consider this linq query:
        Event evnt = new Event();

        var result = evnt.AttendeesList.Any((attnds) => attnds.Property == constproperty && attnds.Value == constValue);


        // I want to create an Expression tree for above linq query. I need something like this:
        ParameterExpression parameter = Expression.Parameter(typeof(Attendees));
        Expression left = Expression.Property(parameter, typeof(ComplexProperty).GetProperty("Property"));
        // complete this piece.......

    }
}

我想为Linq.Expressions.Expression创建evnt.AttendeesList.Any((attnds) => attnds.Property == constproperty && attnds.Value == constValue);  这个linq查询。 How to query collection with Linq.Expressions看起来很相似,但我的linq表达式中有Any

请帮忙。

1 个答案:

答案 0 :(得分:1)

这将为您提供一个开始:

ParameterExpression parameter = Expression.Parameter(typeof(Attendees));
Expression left = Expression.Equal(Expression.Property(parameter, "Property"), Expression.Constant(constproperty));

var objType = constValue == null ? typeof(object) : constValue.GetType();
var convertLeft = Expression.Convert(Expression.Property(parameter, "Value"), objType);
var convertRight = Expression.Convert(Expression.Constant(constValue), objType);
Expression right = Expression.Equal(convertLeft, convertRight);
Expression joined = Expression.And(left, right);

var anyMethod = typeof(Queryable).GetMethods().Where(m => m.Name=="Any" && m.GetParameters().Count() == 2).First().MakeGenericMethod(typeof(Attendees));
var call = Expression.Call(anyMethod, Expression.Constant(evnt.AttendeesList, typeof(IQueryable<Attendees>)), Expression.Lambda(joined, parameter));

为了便于使用,我将Value更改为int类型。如果要将其保留为对象,则需要在right表达式中添加Expression.Convert()调用。