2012-10-12 2 views
0

У меня есть класс представляет общий объект ФильтрующегоОбработки NULLABLE ссылки при построении LambdaExpression динамически

public class Filter 
{ 
    public string column { get; set; } 
    public string operator { get; set; } 
    public string data { get; set; } 
} 

, что я могу превратить в течение LambdaExpression благодаря коду, как этот

public LambdaExpression ToExpression(IQueryable query) { 
    LambdaExpression toReturn = null; 
    ParameterExpression parameter = Expression.Parameter(query.ElementType, "p"); 
    MemberExpression memberAccess = GetMemberExpression(column, parameter); 
    ConstantExpression filter = Expression.Constant(Convert.ChangeType(data, memberAccess.Type)); 
    WhereOperation condition = (WhereOperation)StringEnum.Parse(typeof(WhereOperation), operator); 
    LambdaExpression lambda = BuildLambdaExpression(memberAccess, filter, parameter, condition, data); 
    if (toReturn == null) { 
     toReturn = lambda; 
    } 
    return toReturn; 
} 

согласно требование Filter член column может содержать своего рода навигационный синтакс для запросов полей, который выражается как FieldA.FieldB.Description, что переводит на:

  • Получить значение типа Т возвращаемое из свойства
  • FieldA Получить значение типа T1 возвращается из FieldB Т
  • Получить значение типа Т2 возвращается из описания T2

в результате лямбда, как этот: p.FieldA.FieldB.Description == "data" и я могу использовать этот результат в качестве параметра метода Where расширения любого IQueryable

Проблема возникает, когда один из членов навигационного запроса - тип Nullable. В этом случае, если предположить, FieldA обнуляемый, правильный лямбда должен быть

p.FieldA != null && p.FieldA.FieldB.Description == "data"

Я пытался осуществить эту проверку при построении MemberExpression объекта, используя код как этого

MemberExpression memberAccess = null; 
foreach (var property in column.Split('.')) { 
    memberAccess = MemberExpression.Property(memberAccess ?? (p as Expression), property); 
    Type memberType = memberAccess.Type; 
    if (memberType.IsGenericType && 
     memberType.GetGenericTypeDefinition() == typeof(Nullable<>)) { 

     //Create here an expression of type : memberAccess != null 
    } 
} 

, что хорошо для примитивных типов, но не работает, например, с другими объектными ссылками, например EF EntityReference экземплярами объектов. Я знаю, что я мог бы просто добавить еще одно условие к предыдущему if как

if ((memberType.IsGenericType && 
     memberType.GetGenericTypeDefinition() == typeof(Nullable<>)) || 
     memberType.IsClass) { 
} 

но мне кажется, слишком много общего производства лямбда слишком много условий и большинство из них может быть неполезным.

Есть ли способ улучшить индивидуализацию ссылок на NULL?

+0

Если выражение предназначено для Entity Framework, я бы не стал беспокоиться. 'p.FieldA.FieldB.Description ==" data "' просто будет ложным без каких-либо исключений, если 'FieldA' или' FieldB' равно null. Если это предназначено для компиляции и запуска в памяти, это еще одна история. –

+0

Я использую первый выпуск EF, тот, который работает с .NET 3.5. Если я делаю запрос, как в примере, запрос просто не применяется, и результат подобен тому, как я бы не указал какой-либо фильтр ... – Lorenzo

ответ

3

Вы можете сделать нулевую проверку безусловной. Проверка типа значения для null не является незаконной.

+0

Мой класс Filter уже используется в более широком контексте с группами и другим списком правил. Если я сделаю проверку безусловной, количество выражений в некоторых случаях может быстро увеличиться, даже если они не являются строго необходимыми. Это повлияет на выступления? – Lorenzo

+1

@Lorenzo Проверка на null не более или менее работает, чем проверка того, является ли значение нулевым, поэтому проверка, чтобы проверить, нужна ли вам нулевая проверка, - это та же самая работа в случае объекта, который не является nullable, и * больше * работать в случае объекта с нулевым значением. – Servy

+0

@ Lorenzo: Ну, каждая дополнительная операция добавляет немного к накладным расходам, конечно. Но, с другой стороны, подавляющее большинство типов, используемых в вашем сценарии, будут ссылочными типами и в любом случае нуждаются в нулевой проверке. –

 Смежные вопросы

  • Нет связанных вопросов^_^