我正在寻找一个方式做动态如下:Expression.Call和计数
var q = context.Subscription
.Include("Client")
.Include("Invoices")
Where(s=>s.Client.Invoices.Count(i=>i.InvoiceID == SomeInt) > 0);
我想动态生成式的左侧:
Expression left = s => s.Client.Invoices.Count(i => i.InvoiceID == iSomeVar); //!
Expression right = Expression.Constant(0);
var binary = Expression.GreaterThan(left, right);
谢谢!
经更新的票据:
请注意:最终结果必须是
Expression<Func<T, bool>>
简易版:
// To give clear idea, all what I want to achieve is to determine
// whether specific record exists in reference table using known Path.
// Ultimately I want to extend following function (which works great by
// the way, but for simple operations)
static Expression CreateExpression<T>(string propertyPath,
object propertyValue,
ParameterExpression parameterExpression)
{
PropertyInfo property = typeof(T).GetProperty(propertyName);
MemberExpression left = Expression.Property(parameterExpression, property);
ConstantExpression right = Expression.Constant(0);
BinaryExpression binary = Expression.GreaterThan(left, right);
return binary;
}
// And I want to call this function and get result exactly as shown below:
Expression result =
CreateExpression<Subscription>("Client.Invoices.InvoiceID",
theID,
valueSelector.Parameters.Single());
// Where result will be:
// t => t.Client.Invoices.Count(i => i.InvoiceID == theID) > 0;
扩展版本:
// 1) I'm using Silverlight 4, EF, RIA.
// 2) At the server side I have a function GetSubscriptionsByCriteria
// that looks about it:
public IQueryable<Subscription> GetSubscriptionsByCriteria(...)
{
var query = this.ObjectContext.Subscriptions.Include("Client")
.Include("Client.Invoices");
var criteria = BuildCriteria(...);
return query.Where(criteria)
}
// 3) BuildCriteria(...) function gathers Expressions and
// aggregates it into the single Expression with different
// AND/OR conditions, something like that:
public Expression<Func<Subscription, bool>> BuildCriteria(
List<SearchFilter> filters,
Expression<Func<Subscription, bool>> valueSelector)
{
List<Expression> filterExpressions = new List<Expression>();
...
Expression expr = CreateExpression<Subscription>(
sfItem.DBPropertyName,
sfItem.DBPropertyValue,
paramExpression,
sf.SearchCondition);
filterExpressions.Add(expr);
...
var filterBody =
filterExpressions.Aggregate<Expression>(
(accumulate, equal) => Expression.And(accumulate, equal));
return Expression
.Lambda<Func<Subscription, bool>>(filterBody, paramExpression);
}
// 4) Here is the simplified version of CreateExpression function:
static Expression CreateExpression<T>(string propertyName,
object propertyValue,
ParameterExpression paramExpression)
{
PropertyInfo property = typeof(T).GetProperty(propertyName);
ConstantExpression right = Expression.Constant(0);
MemberExpression left = Expression.Property(paramExpression, property);
return binary = Expression.Equals(left, right);
}
所以,我希望现在很清楚为什么我需要在原始文章中左侧的表达式。试图尽可能做到这一点。
P.S.不要让这太混乱了,所以我觉得我需要做ёExpression.Call(...)ё: 当我运行下面的代码,并打破它,看看我的DebugView注意到这一点:
Expression<Func<Subscription, bool>> predicate =
t => t.Client.Invoices.Count(i => i.InvoiceID == 5) > 0;
BinaryExpression eq = (BinaryExpression)predicate.Body;
var left = eq.Left; // <-- See DEBUG VIEW
var right = eq.Right;
// DEBUG VIEW:
// Arguments: Count = 2
// [0] = {t.Client.Invoices}
// [1] = {i => (i.InvoiceID == 5)}
// DebugView: ".Call System.Linq.Enumerable.Count(
// ($t.Client).ClientInvoices,
// .Lambda#Lambda1<System.Func`2[SLApp.Web.Invoice,System.Boolean]>)
// .Lambda#Lambda1<System.Func`2[SLApp.Web.Invoice,System.Boolean]>
// (SLApp.Web.ClientInvoice $i){ $i.ClientInvoiceID == 5 }"
谢谢,但您已链接的链接rovided不涉及我遇到的问题 – Max 2011-05-14 17:06:37
非常感谢您回复此问题,但您提供的解决方案仍然无法解决问题。我真的需要一个左侧的表达式,我试图解释为什么在上面的帖子。 – Max 2011-05-15 05:47:43
好吧,我现在正在做你正在做的,好的工作解释更好。我仍然不确定你需要表情,我会告诉你为什么。你总是在右侧使用> 0,所以这是恒定的。如果你有所不同,那么你应该把它变成动态的。使一切变得动态并不是更好的设计。在我看来,最好的设计就是尽可能简单和尽可能地解决问题。我会编辑我的答案,让我知道你在想什么。 – Milimetric 2011-05-15 11:13:24