Запустил тестовые проект — все супер все работает.
Создал новый проект скопировал туда классы попробовал пример — не работает
Стал копать в чем дело. Оказывается если проект компилировать по dotNET4 то даже тесты разработчиков не работают а если под 3.5 то все нормально работает .
После изучения кода понял, что просто в 4-ом фреймворке сильно переработана система выражений, поэтому данный сериализатор не работает
Пробовал Dynamic LINQ, так он только из строки может создать выражение, а по выражению сделать строку не может...
Здравствуйте, gandjustas, Вы писали:
G>Здравствуйте, _WerWolf_, Вы писали:
_WW>>Не подскажете какой-нибудь сериализатор выражений (Expression<Func<TEntity, TValue>>)?
G>А зачем?
G>Прошлый раз обсуждение закончилось тем что не стоит этого делать.
К сожалению прошлого раза не видел
На а зачем? Для передачи параметром в WCF сервис.
С выражениями проще и приятнее работать чем например со строками.
Склеивать строки более опасно чем оперировать строками, плюс теряются проверки времени выполнения.
Я конечно использую StaticReflection для того что бы по минимуму использовать строки, но это все равно как-то не удобно
Здравствуйте, _WerWolf_, Вы писали:
_WW>Здравствуйте, gandjustas, Вы писали:
G>>Здравствуйте, _WerWolf_, Вы писали:
_WW>>>Не подскажете какой-нибудь сериализатор выражений (Expression<Func<TEntity, TValue>>)?
G>>А зачем?
G>>Прошлый раз обсуждение закончилось тем что не стоит этого делать.
_WW>К сожалению прошлого раза не видел
_WW>На а зачем? Для передачи параметром в WCF сервис.
И что там с ним делать?
_WW>С выражениями проще и приятнее работать чем например со строками. _WW>Склеивать строки более опасно чем оперировать строками, плюс теряются проверки времени выполнения.
Ну это на клиенте. На сервере то все равно ручками надо expressions обрабатывать.
Здравствуйте, gandjustas, Вы писали:
_WW>>На а зачем? Для передачи параметром в WCF сервис. G>И что там с ним делать?
_WW>>С выражениями проще и приятнее работать чем например со строками. _WW>>Склеивать строки более опасно чем оперировать строками, плюс теряются проверки времени выполнения. G>Ну это на клиенте. На сервере то все равно ручками надо expressions обрабатывать.
class Service1 : IService1
{
public IList<DomainObject1> GetAll( Expression<Func<DomainObject1, bool>> filter )
{
var db = new DB();
return db.DomainObjects1.Where( filter ).ToList().AsReadOnly();
}
}
И что плохого в том что я хочу передать на сервис Expression, по которому я красиво смогу отфильтровать объекты?
Лично мне такой подход кажется более чем удобным.
В случае Dynamic LINQ все тоже может более или менее красиво выглядеть, тем более что не получится в строке передать какой-то эксплойт.
Писать конвертор из выражения в строку — достаточно тривиальная задача, тем более что парсить уже ничего не надо, а достаточно лишь обойти дерево.
Здравствуйте, _WerWolf_, Вы писали:
_WW>Здравствуйте, gandjustas, Вы писали:
_WW>>>На а зачем? Для передачи параметром в WCF сервис. G>>И что там с ним делать?
_WW>>>С выражениями проще и приятнее работать чем например со строками. _WW>>>Склеивать строки более опасно чем оперировать строками, плюс теряются проверки времени выполнения. G>>Ну это на клиенте. На сервере то все равно ручками надо expressions обрабатывать.
_WW>Почему ручками?
_WW>Допустим у меня есть:
_WW>class DomainObject1 { int Id; string Name; }
_WW>interface IService1 _WW>{ _WW> IList<DomainObject1> GetAll( Expression<Func<DomainObject1, bool>> filter ); _WW>}
_WW>class Service1 : IService1 _WW>{ _WW> public IList<DomainObject1> GetAll( Expression<Func<DomainObject1, bool>> filter ) _WW> { _WW> var db = new DB(); _WW> return db.DomainObjects1.Where( filter ).ToList().AsReadOnly(); _WW> } _WW>}
Ну примерно так я и думал.
_WW>И что плохого в том что я хочу передать на сервис Expression, по которому я красиво смогу отфильтровать объекты?
Жаль не могу найти ссылку на обсуждение.
_WW>Лично мне такой подход кажется более чем удобным.
Вкратце: не стоит так делать.
_WW>В случае Dynamic LINQ все тоже может более или менее красиво выглядеть, тем более что не получится в строке передать какой-то эксплойт.
Тем не менее передачей произвольного Linq запроса легко можно положить сервер.
_WW>Писать конвертор из выражения в строку — достаточно тривиальная задача, тем более что парсить уже ничего не надо, а достаточно лишь обойти дерево.
Expression в строку — тривиальная задача?
_WW>А что предлагаете вы?
ADO.NET Data Services, WCF Ria Services.
Здравствуйте, gandjustas, Вы писали:
G>Здравствуйте, _WerWolf_, Вы писали:
_WW>>В случае Dynamic LINQ все тоже может более или менее красиво выглядеть, тем более что не получится в строке передать какой-то эксплойт. G>Тем не менее передачей произвольного Linq запроса легко можно положить сервер.
_WW>>А что предлагаете вы? G>ADO.NET Data Services, WCF Ria Services.
Если бы ограничения стояли только в передаче LINQ запроса на сервер
В сервисах сосредоточена достаточно сложная бизнес логика которая распределена между различными серверами.
Но иногда этим сервисам так же нужно выражение для выбора определённых данных с базы.
Именно по этой причине отпали ADO.NET Data Services. Так как для чистого доступа к данным они действительно супер! Но допустим тот же Epand (Include) на не EntityFramework сходу прикрутить не удалось, хотя я надеюсь что это был лишь вопрос времени.
WCF Ria Services — выглядят гораздо более привлекательными в этом плане, все таки доменная модель.
Но по ряду причин тоже пока остается в сторонке.
Но всё равно спасибо к WCF Ria Services я таки обязательно присмотрюсь поближе.
_WW>>Писать конвертор из выражения в строку — достаточно тривиальная задача, тем более что парсить уже ничего не надо, а достаточно лишь обойти дерево. G> Expression в строку — тривиальная задача?
А вот тут вот очень интересный вопрос. Я пока сложностей не вижу.
Но вы заставили меня задуматься, ушел писать конвертер.
Как сделаю поделюсь информацией.
Здравствуйте, _WerWolf_, Вы писали:
_WW>Здравствуйте, gandjustas, Вы писали:
G>>Здравствуйте, _WerWolf_, Вы писали:
_WW>>>В случае Dynamic LINQ все тоже может более или менее красиво выглядеть, тем более что не получится в строке передать какой-то эксплойт. G>>Тем не менее передачей произвольного Linq запроса легко можно положить сервер.
_WW>>>А что предлагаете вы? G>>ADO.NET Data Services, WCF Ria Services.
_WW>Если бы ограничения стояли только в передаче LINQ запроса на сервер
Суть в том что не надо передавать expression tree, это слишком общая конструкция. Нужен некоторый DSL, который будет описывать запрос, а Linq будет мапиться в этот DSL.
_WW>В сервисах сосредоточена достаточно сложная бизнес логика которая распределена между различными серверами.
В сервисах сосредоточена ... распределена между серверами.
Это как вообще? Разве нельзя сделать "сложную логику" с помощью WCF Data Services или Ria Services?
_WW>Но иногда этим сервисам так же нужно выражение для выбора определённых данных с базы.
Не сомневаюсь.
_WW>Именно по этой причине отпали ADO.NET Data Services. Так как для чистого доступа к данным они действительно супер! Но допустим тот же Epand (Include) на не EntityFramework сходу прикрутить не удалось, хотя я надеюсь что это был лишь вопрос времени.
А причем тут expand? И чем EF не устраивает?
_WW>>>Писать конвертор из выражения в строку — достаточно тривиальная задача, тем более что парсить уже ничего не надо, а достаточно лишь обойти дерево. G>> Expression в строку — тривиальная задача?
_WW>А вот тут вот очень интересный вопрос. Я пока сложностей не вижу. _WW>Но вы заставили меня задуматься, ушел писать конвертер. _WW>Как сделаю поделюсь информацией.
Довольно громоздкий визитор получается, как ни крути. Несмотря на то что код довольно простой.
Но при сериализации expression есть другая проблема — как передавать ссылки на классы
Здравствуйте, gandjustas, Вы писали:
G>Но при сериализации expression есть другая проблема — как передавать ссылки на классы
Думаю, стоит ограничится только значениями, вычисленными на клиенте, и специальным образом помечать объекты-аргументы лямбды. Если найдены другие ссылки — бросать исключение, т.к. толку от этих ссылок на сервере.
Здравствуйте, sto, Вы писали:
sto>Здравствуйте, gandjustas, Вы писали:
G>>Но при сериализации expression есть другая проблема — как передавать ссылки на классы sto>Думаю, стоит ограничится только значениями, вычисленными на клиенте, и специальным образом помечать объекты-аргументы лямбды. Если найдены другие ссылки — бросать исключение, т.к. толку от этих ссылок на сервере.
Тот кож, который сериализует expression для .NET 3.5, умеет обращаться с ссылками на классы
Но это не отменяет факта избыточности сериализации expression.
public static string Serialize<T>(this Expression<Func<T, bool>> expression)
{
// тут мы схлопываем все ссылки на переменные/методы и т.п., используемые в экспрешене, в значения для сериализации.
var expressionEvaluated = Evaluator.PartialEval(expression);
var editableExpression = (EditableLambdaExpression)EditableExpression.CreateEditableExpression(expressionEvaluated);
return editableExpression.Serialize(); <- datacontractserializer
}
Server:
var expression = ExpressionHelper.DeserializeExpression(serializedExpression, typeof(EditableLambdaExpression));
// используем expression для построения условий выборки в сиквеле/etc.
public static Expression DeserializeExpression(string serializedExpression, Type expressionType)
{
var dcs = new DataContractSerializer(expressionType);
using (var ms = new StringReader(serializedExpression))
using (var xdr = XmlReader.Create(ms))
{
var editableExpression = dcs.ReadObject(xdr) as EditableExpression;
return (editableExpression != null) ? editableExpression.ToExpression() : null;
}
}
В итоге получается очень гибко юзать с клиента/без DTO для параметров поиска и т.п.