Я пытаюсь создать динамический запрос 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 == ""
Но это работая, и как программист, я чувствую принципиальность, мне нужно выяснить, как это сделать, используя статический метод.
Я очень ценю ваш ответ. Я отредактировал выше, чтобы предоставить вам дополнительную информацию. Ваше решение выше, вероятно, будет работать, и я скоро его проверю, но, возможно, у вас есть ответ на вопрос и в редактировании. – Magn3s1um
Я на самом деле использую очень похожую логику. Я имею в виду, привязать объект «Filter» на сервере, а затем преобразовать его в «Ограничения» (Criteria API). И я бы сказал, его можно было бы использовать в вашем случае аналогичным образом. Как это работает? вместо создания выражений я передаю критерии по нескольким методам расширения. Если кто-либо из них может правильно прочитать фильтр, он добавляет ограничения. Ограничения имеют сильную поддержку строк, поэтому, если я действительно применяю достаточную проверку на привязку фильтра, я могу использовать строки. Может быть, это может помочь, хотя это не ответ на построение выражений по статическим методам;) –
Мы переключились с Критерии на Linq на nhibernate, поэтому нужны выражения. Я увижу, если == null || "". Я отправлю результаты, и если это сработает, я дам вам ответ. Еще раз спасибо – Magn3s1um