我怎么能做一个Func <object [],Expression <Func <T,bool >>>动态?

Pou*_*sen 5 .net c# lambda

我正在做一个.Find(objects [] keys)方法,它动态创建一个lambda函数来查询数据库.

基本上我想要的是:

var mykeys = new Guid("37ec1659-b35e-46c9-a7fc-e9802644ca1a");
IQueryable<T> database ;
Func<object[],Expression<Func<T,bool>>> objectFinder = CreateKeyExpression(typeof(T));
var foundObject = database.FirstOrDefault(objectFinder(mykeys));
Run Code Online (Sandbox Code Playgroud)

private LambdaExpression CreateKeyExpression(Type C1Type)
{

    ParameterExpression instanceParameter = Expression.Parameter(C1Type);
    ParameterExpression keyParameters = Expression.Parameter(typeof(object[]));

    PropertyInfo[] objectKeys = C1Type.GetKeyProperties().ToArray();
    var expr = Expression.Equal( Expression.TypeAs( Expression.Property(instanceParameter,objectKeys[0]),typeof(object)),
      Expression.ArrayIndex(keyParameters,Expression.Constant(0))); 


    for (int i = 1; i < objectKeys.Length; i++)
    {
        expr = Expression.AndAlso(expr, Expression.Equal(
            Expression.Property(instanceParameter,objectKeys[i]),
            Expression.ArrayIndex(keyParameters,Expression.Constant(i))
            )); 

    }

    var lmp= Expression.Lambda(expr, instanceParameter);

    return Expression.Lambda(lmp, keyParameters);
}
Run Code Online (Sandbox Code Playgroud)

有关如何实现这一目标的任何想法?上面给出了一个Func<object[],Func<T,bool>>,它使IQueryable成为IEnumerable,这意味着它不会在数据库端执行.

Vya*_*kov 2

您需要使用该Expression.Constant方法而不是Expression.ArrayIndex,因为您将无法使用该FirstOrDefault方法将键值 \xe2\x80\x8b\xe2\x80\x8 传递到表达式数组。

\n\n
private static LambdaExpression CreateKeyExpression(Type C1Type, object[] parameters)\n{\n    var instanceParameter = Expression.Parameter(C1Type);\n    PropertyInfo[] objectKeys = C1Type.GetKeyProperties().ToArray();\n\n    var expr = Expression.Equal(Expression.Property(instanceParameter, objectKeys[0]),\n        Expression.Constant(parameters[0], objectKeys[0].PropertyType));\n\n\n    for (int i = 1; i < objectKeys.Length; i++)\n    {\n        expr = Expression.AndAlso(expr, Expression.Equal(\n            Expression.Property(instanceParameter, objectKeys[i]),\n            Expression.Constant(parameters[i], objectKeys[i].PropertyType)));\n    }\n    return Expression.Lambda(expr, instanceParameter);\n}\n\nvar parameters = new object[] { Guid.NewGuid(), Guid.NewGuid() };\nvar lambdaExpression = CreateKeyExpression(typeof(TestClass), parameters);\nvar testClasses = new List<TestClass>() { new TestClass { Id = (Guid)parameters[0], Id1 = (Guid)parameters[1] } };\nvar testClass = testClasses.AsQueryable().FirstOrDefault((Expression<Func<TestClass, bool>>)lambdaExpression);\n
Run Code Online (Sandbox Code Playgroud)\n