2012-02-01 2 views
1

여기에 문제가 있습니다 :문자열에서 표현식 만들기 (null 참조)

우리는 사용자가 검색, 정렬, 페이지 매김 등과 같은 일부 기능을 수행 할 수 있도록 테이블 객체를 사용합니다. 하지만 기능 중 하나에 문제가 있습니다. 정렬 (= OrderBy).

사실, 정렬을 허용하기 위해 모든 열에 표현식을 나타내는 문자열을 설정합니다. 예를 들어, 표현식이 Person => Person.Id 인 경우 문자열은 Id입니다. 식이 Person => Person.Address.Street 인 경우 문자열은 Address.Street입니다.

첫 번째 경우 (Person => Person.Id)는 하위 오브젝트가 아니기 때문에 효과가 있습니다. 두 번째 경우 (Person => Person.Address.Street)는 Address 객체가 null 일 수 있기 때문에 발생하지 않습니다.

나는 다음과 같은 방법 타 게시물에 발견의 ORDERBY 문자열에서 수행 할 수 있도록 :
public static IOrderedQueryable<T> OrderBy<T>(this IQueryable<T> source, string property) 
{ 
    return ApplyOrder<T>(source, property, "OrderBy"); 
} 

public static IOrderedQueryable<T> OrderByDescending<T>(this IQueryable<T> source, string property) 
{ 
    return ApplyOrder<T>(source, property, "OrderByDescending"); 
} 

public static IOrderedQueryable<T> ThenBy<T>(this IOrderedQueryable<T> source, string property) 
{ 
    return ApplyOrder<T>(source, property, "ThenBy"); 
} 

public static IOrderedQueryable<T> ThenByDescending<T>(this IOrderedQueryable<T> source, string property) 
{ 
    return ApplyOrder<T>(source, property, "ThenByDescending"); 
} 

private static IOrderedQueryable<T> ApplyOrder<T>(IQueryable<T> source, string property, string methodName) 
{ 
    string[] props = property.Split('.'); 
    Type type = typeof(T); 
    ParameterExpression arg = Expression.Parameter(type, "x"); 
    Expression expr = arg; 
    foreach (string prop in props) 
    { 
     // use reflection (not ComponentModel) to mirror LINQ 
     PropertyInfo pi = type.GetProperty(prop); 
     expr = Expression.Property(expr, pi); 
     type = pi.PropertyType; 
    } 
    Type delegateType = typeof(Func<,>).MakeGenericType(typeof(T), type); 
    LambdaExpression lambda = Expression.Lambda(delegateType, expr, arg); 
    object result = typeof(Queryable).GetMethods().Single(
    method => method.Name == methodName 
     && method.IsGenericMethodDefinition 
     && method.GetGenericArguments().Length == 2 
     && method.GetParameters().Length == 2) 
      .MakeGenericMethod(typeof(T), type) 
      .Invoke(null, new object[] { source, lambda }); 
    return (IOrderedQueryable<T>)result; 
} 

당신의 날 조건을 추가 할 수 있도록 할 생각이 있습니까

이없는 것 하위 객체 == null로 객체를 선택 하시겠습니까? 또는 null 인 객체에서 속성에 액세스하려고 시도하지 못하게 하시겠습니까?

편집 :

체크과 같이 보일 것이다 : list.OrderBy (!? X => (x.Address을 = NULL을) x.Address.Street : String.Empty로).

그래서 x와 최종 필드 사이의 모든 개체에 대해 null 체크를 추가해야합니다. 이러한 방법을 사용하여이를 수행 할 수 있습니까?

편집 2 :

나는

expr = Expression.Condition(
       Expression.Equal(expr, Expression.Constant(null)), 
       Expression.Constant(String.Empty), 
       Expression.Property(expr, pi)); 

에 의해

Expression.Property(expr, pi); 

를 대체하기 위해 시도했다 그러나 작동하지 않는 것 같다. 내가 EXPR 액세스 필드의 기본값을 알게되어있어 방법

Argument types do not match 

어떤 생각 : 나는 다음과 같은 예외가?

+0

OrderBy 메서드를 호출하기 전에 속성이 'null'인지 확인할 수 있습니까? – Mentoliptus

+0

그게 내가하고 싶지 않아. 차라리 다른 부분을 포함하여 코드를 여러 부분으로 나눌 필요가 없도록 확인할 것입니다. 하지만이 수표를 포함시키는 법을 모르겠습니다. – Whoami

+0

내 대답보기 http://stackoverflow.com/questions/17647627/dynamic-linq-order-by-on-nested-property-with-null-properties/31450534#31450534 –

답변

0

속성 유형으로 널 (null) 상수를 작성하십시오.

expr = Expression.Condition(Expression.Equal(expr, Expression.Constant(null, expr.Type)), 
       Expression.Constant(String.Empty), 
       Expression.Property(expr, pi));