2012-01-23 3 views
13

다른 것들과 결합하여 필터링을 위해 다소 큰 식 트리에 결합 할 람다 식을 작성하려고합니다. 하위 컬렉션 속성으로 필터링해야 할 때까지 제대로 작동합니다.컬렉션 속성을 필터링하기 위해 동적 식 트리 만들기

루트 객체의 속성 인 컬렉션의 속성에서 Any()를 사용하여 필터링하는 람다 식을 어떻게 작성합니까?

예 :

CurrentDataSource.Offices.Where(o => o.base_Trades.Any(t => t.Name == "test")) 

이것은 내가 정적 표현을 구축 할 것입니다하지만 동적으로 구축해야하는 방법이다. 혼란을 드려 죄송합니다.

편집 :

IQueryable<Office> officeQuery = CurrentDataSource.Offices.AsQueryable<Office>(); 
ParameterExpression pe = Expression.Parameter(typeof(Office), "Office"); 
ParameterExpression tpe = Expression.Parameter(typeof(Trades), "Trades"); 

Expression SimpleWhere = null; 
Expression ComplexWhere = null; 
foreach (ServerSideFilterObject fo in ssfo) 
{ 
    SimpleWhere = null; 
    foreach (String value in fo.FilterValues) 
    { 
     if (!CollectionProperties.Contains(fo.PropertyName)) 
     { 
      //Handle singleton lambda logic here. 
      Expression left = Expression.Property(pe, typeof(Office).GetProperty(fo.PropertyName)); 
      Expression right = Expression.Constant(value); 
      if (SimpleWhere == null) 
      { 
       SimpleWhere = Expression.Equal(left, right); 
      } 
      else 
      { 
       Expression e1 = Expression.Equal(left, right); 
       SimpleWhere = Expression.Or(SimpleWhere, e1); 
      } 
     } 
     else 
     { 
      //handle inner Collection lambda logic here. 
      Expression left = Expression.Property(tpe, typeof(Trades).GetProperty("Name")); 
      Expression right = Expression.Constant(value); 
      Expression InnerLambda = Expression.Equal(left, right); 

      //Problem area. 
      Expression OfficeAndProperty = Expression.Property(pe, typeof(Office).GetProperty(fo.PropertyName)); 
      Expression OuterLambda = Expression.Call(OfficeAndProperty, typeof(Trades).GetMethod("Any", new Type[] { typeof(Expression) }),InnerLambda); 

      if (SimpleWhere == null) 
       SimpleWhere = OuterLambda; 
      else 
       SimpleWhere = Expression.Or(SimpleWhere, OuterLambda); 
     } 
    } 
    if (ComplexWhere == null) 
     ComplexWhere = SimpleWhere; 
    else 
     ComplexWhere = Expression.And(ComplexWhere, SimpleWhere); 
} 
MethodCallExpression whereCallExpression = Expression.Call(typeof(Queryable), "Where", new Type[] { officeQuery.ElementType }, officeQuery.Expression, Expression.Lambda<Func<Office, bool>>(ComplexWhere, new ParameterExpression[] { pe })); 
results = officeQuery.Provider.CreateQuery<Office>(whereCallExpression); 
+0

표현식 트리를 만드는 방법을 묻는 중입니까? – SLaks

+0

귀하의 예에서 계층 구조가 어떻게 작동하는지 모르겠습니다. 좀 더 자세히 설명해 주시겠습니까? 사무실은 근원지입니까? 그리고 각 사무실에는 거래의 모음이 있습니까? 그리고 당신은 무역의 이름을 걸러 내고 싶습니까 ?? 필터는 내가 잃어버린 부분이다. 죄송합니다. –

+0

아니요, 내부 메서드 호출 및 매개 변수 식을 사용하여 식을 작성하는 데 사용되는 구문을 확신 할 수 없습니다. 이 경우 Any 매개 변수가 정의와 일치하지 않기 때문에 Any()를 찾을 수 없다는 오류가 발생합니다. 이 경우 구문에 어긋나거나 Any()가 사용중인 방식으로 지원되지 않기 때문에 그 이유가 확실하지 않습니다. – George

답변

9

솔루션을 발견. 전에 올바른 방법으로 어떤 방법을 찾지 않았습니다.

Expression left = Expression.Property(tpe, typeof(Trades).GetProperty("Name")); 
Expression right = Expression.Constant(value); 
Expression InnerLambda = Expression.Equal(left, right); 
Expression<Func<Trades, bool>> innerFunction = Expression.Lambda<Func<Trades, bool>>(InnerLambda, tpe); 

method = typeof(Enumerable).GetMethods().Where(m => m.Name == "Any" && m.GetParameters().Length == 2).Single().MakeGenericMethod(typeof(Trades)); 
OuterLambda = Expression.Call(method, Expression.Property(pe, typeof(Office).GetProperty(fo.PropertyName)),innerFunction); 
0

귀하의 예제는 귀하의 의견에 따라 작동합니다 당신이 나와 무슨 : 여기가 덜 복잡 표현을 처리하는 방법의 조각입니다. 우리는 필드의 특정 컬렉션이 템플릿이, 그 필드가 요구 될 수

Templates.Where(t => t.TemplateFields.Any(f => f.Required == 'Y')) 

: 여기에 내가 작업 내용의 예입니다. 그래서 위의 문장에서 필요한 필드가있는 템플릿을 얻을 수 있습니다.

도움이 되었으면 좋겠지 만 ... 적어도 당신이하려는 일을 확인하십시오. 이것에 대해 더 궁금한 점이 있으면 알려주십시오.

행운을 빈다.

+0

이것은 내가 작업하고있는 것과 비슷하지만 반사음을 사용하여 동적으로 lamda 표현식을 작성해야 필터가 세트의 다른 필터를 통합 할 수 있습니다. – George

0

CurrentDataSource.Offices.Where(o => o.base_Trades.Any(t => t.Name == "test")) 

만큼 o.base_TradesIEnumerable<Trade>를 구현하는대로 작동합니다 제공되는 코드입니다. o.base_TradesIEnumerable 만 구현하는 경우 o.base_Trades의 모든 요소가 Trade 유형 또는 OfType<Trade>()의 요소 (호환되지 않는 유형) 일 수 있는지 확인하려면 Cast<Trade>()을 사용해야합니다. 다음과 같을 것이다

는 :

CurrentDataSource.Offices 
    .Where(o => o.base_Trades.Cast<Trade>.Any(t => t.Name == "test")) 
1

동적 인 linq라는 라이브러리를 실제로 사용 하시겠습니까? http://nuget.org/packages/DynamicLINQ

쿼리를 문자열로 저장할 수 있으며 매우 복잡한 쿼리를 지원합니다. 표정 나무는 악몽이다.

+0

훌륭한 라이브러리입니다. 저는이 라이브러리도 사용합니다. 그러나 'myIQueryable.OrderBy (x => x.MyCollection.Select (y => y.Myproperty))와 같은 콜렉션 속성의 예제 정렬을 지원하지 않습니다. ', 적어도 나는 그것을 작동시킬 수 없다. –

관련 문제