2014-01-24 3 views
2

Я пытаюсь создать динамический запрос nhibernate с помощью выражений. У меня нет проблем с такими функциями, как Contains, StartsWith и EndsWith, но я не могу заставить его работать с IsNullOrEmpty. Вот некоторые контекст:Создание динамического выражения Linq с использованием String.IsNullOrEmpty (string) и Nhibernate

Содержит:

MethodInfo contains = typeof(string).GetMethod("Contains", new Type[] { typeof(string) }); 
ParameterExpression param = Expression.Parameter(typeof(MyType), "x"); 
Expression expression = null; 
PropertyInfo info = typeof(MyType).Property("MyStringProperty"); 
expression = Expression.Property(param, info); 

expression = Expression.Call(expression, info, Expression.Constant("Does it contain this string", typeof(string))); 

В конце всего этого, выражение равно это в отладчике:

expression = { x.MyStringProperty }; 

Я тогда превратить это лямбда exrpression:

var finalExpression = Expression.Lambda<Func<MyType, bool>>(expression, param); 

В конце этого окончательного выражения:

x => x.MyStringProperty.Contains("Does it contain this string"); 

Когда я запускаю это через nhibernate, он делает именно то, что я хочу. С IsNullOrEmpty, хотя, это то, что у меня есть:

MethodInfo isNull = typeof(string).GetMethod("IsNullOrEmpty", new Type[] { typeof(string) }); 
ParameterExpression param = Expression.Parameter(typeof(MyType), "x"); 
PropertyInfo info = typeof(MyType).GetProperty("MyStringProperty"); 
expression = Expression.Property(param, info); 
expression = Expression.Call(isNull, expression); 

В конце всего этого, выражение равно:

expression = { IsNullOrEmpty(x.MyStringProperty) } 

И после преобразования лямбда он превращается в:

finalExpression = { x => IsNullOrEmpty(x) } 

Это выглядит точно так, как должно (хотя я допускаю, возможно, он должен читать string.IsNullOrEmpty (x)), но когда я запускаю его через nhibernate, я получаю ошибку:

NotSupportedException 
Message: Boolean IsNullOrEmpty(System.String) 

Кто-нибудь знает, почему это так? Если я бегу не динамический запрос и рука написать, где положение, как это, она работает без проблем:

nhibernateDataProvider.Where(x => string.IsNullOrEmpty(x.MySTringProperty)); 

Кто знает, почему это/как это исправить?

Edit:

Почему я пытаюсь сделать это:

В моем веб-слое у меня есть этот x.MyStringProperty данные, отображаемые пользователю. У них есть возможность фильтровать это свойство, и я хочу иметь возможность фильтровать данные этими строковыми методами. Веб-слой просто передает эти функции обратно:

BeginsWith 
EndsWith 
Contains 
IsNullOrEmpty 
NotIsNullOrEmpty 

От этих имен я могу напрямую повернуть их в строковые методы, используя приведенный выше код. Из-за этого я могу передать любой тип, который у меня есть на своем веб-уровне, и иметь возможность фильтровать любое свойство строки. Это очень эффективно, потому что для всех моих сотен классов у меня может быть один метод, который заботится о моей фильтрации для каждого класса. Как я уже говорил, он работает с нестатическими методами, потому что выражение построен является:

x -> x.MyStringProperty.NonStaticMethod("SomeFilterValue"); 

Is говорит прямо в документации Expression.Call, что вы должны быть в состоянии сделать это с помощью статических методов, а также.Так как это работает для нестатических методов, там должен быть способом сделать IsNullOrEmpty таким образом, что выражение становится

x -> string.StaticMethod(x.MyStringProperty) 

Я пари, что это будет работать, если я создаю выражение

x -> x.MySTringProperty == null || x.MySTringProperty == "" 

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

ответ

3

Я просто не уверен, чего вы пытаетесь достичь здесь. Язык запросов динамического выражения уже существует: это встроенный поставщик LINQ. Но давайте попробуем дать вам больше информации о его реализации.

Когда встроенный поставщик Linq получает запрос, представленный деревом выражений, шаблон обращения используется для его преобразования в SQL (со средним шагом HQL). Один мощный часть инспекции метод представлен интерфейс IHqlGeneratorForMethod

public interface IHqlGeneratorForMethod 
{ 
    IEnumerable<MethodInfo> SupportedMethods { get; } 
    HqlTreeNode BuildHql(MethodInfo method, Expression targetObject 
      , ReadOnlyCollection<Expression> arguments, HqlTreeBuilder treeBuilder 
      , IHqlExpressionVisitor visitor); 
} 

Важной частью здесь является набор реализаторов:

DictionaryItemGenerator 
DictionaryContainsKeyGenerator 
EqualsGenerator 
BoolEqualsGenerator 
MathGenerator 
AnyHqlGenerator 
AllHqlGenerator 
MinHqlGenerator 
MaxHqlGenerator 
CollectionContainsGenerator 
HqlGeneratorForExtensionMethod 
StartsWithGenerator // StartsWith 
EndsWithGenerator // EndsWith 
ContainsGenerator // Contains 
ToLowerGenerator 
ToUpperGenerator 
SubStringGenerator 
IndexOfGenerator 
ReplaceGenerator 
TrimGenerator 

Как вы можете видеть, есть ответственные за Contains, EndsWith и StartsWith , Но IsNullOrEmpty не может быть найден там.

Другими словами, независимо от того, что вы делаете в глобальном, ваш IsNullOrEmpty должен закончиться в заявлении, как это:

.Where(x => x.MyProperty == null || x.MyProperty == "") 
+0

Я очень ценю ваш ответ. Я отредактировал выше, чтобы предоставить вам дополнительную информацию. Ваше решение выше, вероятно, будет работать, и я скоро его проверю, но, возможно, у вас есть ответ на вопрос и в редактировании. – Magn3s1um

+0

Я на самом деле использую очень похожую логику. Я имею в виду, привязать объект «Filter» на сервере, а затем преобразовать его в «Ограничения» (Criteria API). И я бы сказал, его можно было бы использовать в вашем случае аналогичным образом. Как это работает? вместо создания выражений я передаю критерии по нескольким методам расширения. Если кто-либо из них может правильно прочитать фильтр, он добавляет ограничения. Ограничения имеют сильную поддержку строк, поэтому, если я действительно применяю достаточную проверку на привязку фильтра, я могу использовать строки. Может быть, это может помочь, хотя это не ответ на построение выражений по статическим методам;) –

+1

Мы переключились с Критерии на Linq на nhibernate, поэтому нужны выражения. Я увижу, если == null || "". Я отправлю результаты, и если это сработает, я дам вам ответ. Еще раз спасибо – Magn3s1um

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