Как стать автором
Обновить

Комментарии 16

You are not a Sane, you are insane :)
В хорошем смысле :)
Я тоже использую данный подход в своём проекте. Однако, не понимаю, почему разработчики C# не могли добавить нативную поддержку разворачивания экспрешнов в язык. Лично я не вижу никаких концептуальных проблем. В вашем примере
Expression<Func<int, int, int, int>> g = (a, b, c) => f(a+b,b)*c;
f не может быть воспринята никак, кроме вызова делегата, а значит её можно подставить в экспрешн. Было бы круто =)
Можно спросить Липперта, но я думаю, он ответит, что просто незачем.
Ну, наверное, потому, что экспрешены — всё же навеска. Кроме того, это хороший задел добавить фичу в следующую версию шорпия :)
Я бы не сказал, что expression — это навеска. Это мощный инструмент, на основе которого построен LINQ2* и, например, в .net 4 экспрешенны получили достаточно сильное развитие вполть до возможности представлять в expressions целые методы.
Я имел в виду под «навеской» не малозначимость инструмента для платформы, а степень его интеграции в язык.

А причина отсутствия разворачивания экспрешнов, возможно, — их генерация во время компиляции и сложность с инициализацией замыканий.
Да, очень похоже на замыкания. Плюс f может стать рекурсивной и вообще здесь попахивает проблемой остановки.
С замыканиями по-моему проблем не должно быть. Ваш метод ведь работает с замыканиями?

А вот с рекурсией да, могут возникнуть проблемы.
Есть опыт написание подобного визитора, но только для иных целей:
Полученные выражения могут использоваться как для IQueryable так и для IEnumerable, если инетерсно — могу попробовать написать статью :)
В смысле безопасно использованы: добавляетяс проверка на null
А можно в двух словах, для чего конкретно?
наиример, есть экспрешен вида: Expression<Func<Entity, bool>> f = (e) => e.Field.Other.Name == "qwe";
Если передавать это в IQueryable — все будет хорошо. Есди сделать f.Compile().Invoke(new Entity()) — получим NullReferenceException если какое-то поле в цепочке будет Null.
Мой Visitor превращает такое выражение во что-то типа Expression<Func<Entity, bool>> f = (e) => e != nul && e.Field != null && e.Field.Other != null && e.Field.Other.Name == "qwe";
использую в своих проектах этот подход, вполне читаем, легко был понят коллегами.
//Groovy:
bossName = Employee?.Supervisor?.Manager?.Boss?.Name
//C#:
bossName = Nullify.Get(Employee, e => e.Supervisor, s => s.Manager, m => m.Boss, b => b.Name);
А чем вы рисовали такую красивую схему?
XMind
Клево, но такие подходы интересны небольших приложений, а на практике, когда дело доходит до бизнес функции, советую использовать Specification Pattern, который можно легко тестировать и внести в документацию на систему.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации