Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/299.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_Entity Framework 5 - Fatal编程技术网

C# 根据嵌套集合属性筛选的动态表达式树

C# 根据嵌套集合属性筛选的动态表达式树,c#,linq,entity-framework-5,C#,Linq,Entity Framework 5,我正在使用实体框架,并使用导航属性动态构建查询 对于我的大多数用例,以下功能都很好: private static MethodCallExpression GetNavigationPropertyExpression<T>(string propertyName, int test, ParameterExpression parameter, string subParameter) { var navigationPropertyCol

我正在使用实体框架,并使用导航属性动态构建查询

对于我的大多数用例,以下功能都很好:

private static MethodCallExpression GetNavigationPropertyExpression<T>(string propertyName, int test,
        ParameterExpression parameter, string subParameter)
    {
        var navigationPropertyCollection = Expression.Property(parameter, propertyName);

        var childType = navigationPropertyCollection.Type.GetGenericArguments()[0];

        var anyMethod = typeof(Enumerable).GetMethods().Single(m => m.Name == "Any" && m.GetParameters().Length == 2).MakeGenericMethod(childType);

        var aclAttribute = GetAclAttribute(typeof(T), propertyName);
        var childProperty = aclAttribute.ChildProperty;

        var propertyCollectionGenericArg = childType;
        var serviceLocationsParam = Expression.Parameter(propertyCollectionGenericArg, subParameter);

        var left = Expression.Property(serviceLocationsParam, childProperty);
        var right = Expression.Constant(test, typeof(int));

        var isEqual = Expression.Equal(left, right);
        var subLambda = Expression.Lambda(isEqual, serviceLocationsParam);

        var resultExpression = Expression.Call(anyMethod, navigationPropertyCollection, subLambda);

        return resultExpression;
    }

有了它,就可以构建您的查询:

public static Expression GetNavigationPropertyExpression(Expression parameter, int test, params string[] properties)
{
    Expression resultExpression = null;
    Expression childParameter, navigationPropertyPredicate;
    Type childType = null;

    if (properties.Count() > 1)
    {
        //build path
        parameter = Expression.Property(parameter, properties[0]);
        var isCollection = typeof(IEnumerable).IsAssignableFrom(parameter.Type);
        //if it´s a collection we later need to use the predicate in the methodexpressioncall
        if (isCollection)
        {
            childType = parameter.Type.GetGenericArguments()[0];
            childParameter = Expression.Parameter(childType, childType.Name);
        }
        else
        {
            childParameter = parameter;
        }
        //skip current property and get navigation property expression recursivly
        var innerProperties = properties.Skip(1).ToArray();
        navigationPropertyPredicate = GetNavigationPropertyExpression(childParameter, test, innerProperties);
        if (isCollection)
        {
            //build methodexpressioncall
            var anyMethod = typeof(Enumerable).GetMethods().Single(m => m.Name == "Any" && m.GetParameters().Length == 2);
            anyMethod = anyMethod.MakeGenericMethod(childType);
            navigationPropertyPredicate = Expression.Call(anyMethod, parameter, navigationPropertyPredicate);
            resultExpression = MakeLambda(parameter, navigationPropertyPredicate);
        }
        else
        {
            resultExpression = navigationPropertyPredicate;
        }
    }
    else
    {
        //Formerly from ACLAttribute
        var childProperty = parameter.Type.GetProperty(properties[0]);
        var left = Expression.Property(parameter, childProperty);
        var right = Expression.Constant(test, typeof(int));
        navigationPropertyPredicate = Expression.Equal(left, right);
        resultExpression = MakeLambda(parameter, navigationPropertyPredicate);
    }
    return resultExpression;
} 

private static Expression MakeLambda(Expression parameter, Expression predicate)
{
    var resultParameterVisitor = new ParameterVisitor();
    resultParameterVisitor.Visit(parameter);
    var resultParameter = resultParameterVisitor.Parameter;
    return Expression.Lambda(predicate, (ParameterExpression)resultParameter);
}

private class ParameterVisitor : ExpressionVisitor
{
    public Expression Parameter
    {
        get;
        private set;
    }
    protected override Expression VisitParameter(ParameterExpression node)
    {
        Parameter = node;
        return node;
    }
}
可以这样说:

var parameter = Expression.Parameter(typeof(A), "A");
var expression = ExpressionBuilder.GetNavigationPropertyExpression(parameter, 8,"CollectionOfB", "CollectionOfC", "ID");

好极了工作得很好!谢谢你的帮助!
var parameter = Expression.Parameter(typeof(A), "A");
var expression = ExpressionBuilder.GetNavigationPropertyExpression(parameter, 8,"CollectionOfB", "CollectionOfC", "ID");