Wou*_*ter 7 c# lambda iqueryable where expression-trees
在我的代码中的第(3)点,我定义了一个名为query1的查询,其中我定义了一个.Where lambda表达式.此查询在某种程度上是动态的,但仍包含静态元素,它始终引用Type Employee及其(int)属性ClientID.
现在我非常希望根据方法参数来引用类型及其属性动态,例如,如下面的点(1)所示.
到目前为止我尝试的是通过将(例如)(4),(5)和(6)中记载的更复杂的表达式树替换为使得在点(3)下定义的查询的静态部分完全动态化.但是,当我尝试将所有内容添加到一起时,它说我打电话.参数错误.我不知道如何调用.使用正确的参数来创建一个完全动态的选择.
有人知道解决这个问题吗?我花了一天时间搜索,到目前为止还没有找到解决方案.
dsMain domainService = new dsMain();
//(1)i want to rewrite the following four variables to method-parameters
Type entityType = typeof(Employee);
String targetProperty = "ClientID";
Type entityProperty = typeof(Employee).GetProperty(targetProperty).PropertyType;
int idToDelete = 5;
//(2)create expression-function: idToDelete == entityType.targetProperty (in this case: Employee.ClientID)
ParameterExpression numParam = Expression.Parameter(entityProperty, targetProperty.Substring(0, 3));
ConstantExpression equalTarget = Expression.Constant(idToDelete, idToDelete.GetType());
BinaryExpression intEqualsID = Expression.Equal(numParam, equalTarget);
Expression<Func<int, bool>> lambda1 =
Expression.Lambda<Func<int, bool>>(
intEqualsID,
new ParameterExpression[] { numParam });
//(3)I want to create query1 fully dynamic, so defining Employee or an other type and its property at run time
WhereClause = lambda1.Compile();
IQueryable<Employee> employees = domainService.GetEmployees();
var query1 = employees.Where<Employee>(C => WhereClause.Invoke(C.ClientID)).Expression;
//(4)create the operand body {value(ASP.test_aspx).WhereClause.Invoke(E.ClientID)}
var operandbodyMethod = WhereClause.GetType().GetMethod("Invoke");
var operandbodyType = typeof(System.Boolean);
var operandbodyArgs1Expression = Expression.Parameter(entityType, entityType.Name.Substring(0, 1));
var operandbodyArgs1 = Expression.MakeMemberAccess(operandbodyArgs1Expression, entityType.GetMember(targetProperty)[0]);
var operandBodyObjectExp = Expression.Constant(this, this.GetType());
var operandbodyObject = Expression.MakeMemberAccess(operandBodyObjectExp, this.GetType().GetMember("WhereClause")[0]);
//(5)create the operand {E => value(ASP.test_aspx).WhereClause.Invoke(E.ClientID)}
var operandbody = Expression.Call(operandbodyObject, operandbodyMethod, operandbodyArgs1);
var operandParameter = Expression.Parameter(entityType, entityType.Name.Substring(0, 1));
var operandType = typeof(Func<,>).MakeGenericType(entityType, typeof(System.Boolean));
//(6)
var operand = Expression.Lambda(operandType, operandbody, new ParameterExpression[] { operandParameter });
var expressionType = typeof(Expression<>).MakeGenericType(operandType);
var completeWhereExpression = Expression.MakeUnary(ExpressionType.Quote, operand, expressionType);
//(7)the line below does not work
var query2 = employees.Where<Employee>(completeWhereExpression).Expression;
Run Code Online (Sandbox Code Playgroud)
非常感谢您阅读我的问题!如果您对我的问题有疑问,请询问他们:)
Mar*_*ell 20
这很难孤立地看待,但首先发生的事情是Compile看起来不合适IQueryable- 这很少会起作用(LINQ-to-Objects是例外).
一个相当于WhereClause.Invoke(C.ClientID)是用Expression.Invoke调用子表达式,但即使是这样古怪:LINQ到SQL会支持它,EF(3.5至少)没有(也许"没有",我没有重新检查4.0).最终,如果可能lambda1的Expression<Func<Employee,bool>>话,创建它会更加健壮:
ParameterExpression empParam = Expression.Parameter(typeof(Employee),"emp");
ConstantExpression equalTarget = Expression.Constant(idToDelete, idToDelete.GetType());
BinaryExpression intEqualsID = Expression.Equal(
Expression.PropertyOrField(empParam, targetProperty), equalTarget);
Expression<Func<Exmployee, bool>> lambda1 =
Expression.Lambda<Func<int, bool>>(
intEqualsID,
empParam);
Run Code Online (Sandbox Code Playgroud)
然后通过这个来Where:
var query1 = employees.Where(lambda1);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
9438 次 |
| 最近记录: |