Комментарии 12
А про паттерн Visitor, и про то, что в .net есть готовый ExpressionVisitor
, вы никогда не слышали?
А вот так не проще было?
private Func<object, object> GetGetterMethod()
{
if (_property == null)
throw new ArgumentNullException("property");
var p = Expression.Parameter(typeof(object));
var body = Expression.Property(Expression.Convert(p, _property.DeclaringType), _property);
return Expression.Lambda<Func<object, object>>(Expression.Convert(body, typeof(object)), p).Compile();
}
А еще лучше — собирать функцию для преобразования объекта целиком, а не по одному свойству. Это сэкономит кучу времени на вызовах делегатов.
Теперь по пунктам:
Разбор выражений удобно осуществлять на основе бинарных деревьев выражений.
Разбор выражений удобно осуществлять на основе деревьев выражений. Expressions в .net — не бинарное дерево, а просто дерево: у ConditionalExpression
три дочерних выражения, у MethodCallExpression
и MemberInitExpression
— неограниченный список.
Нам важно добраться до листьев, которые в нашем случае, имеют типы MemberExpression, ConstantExpression
То есть условия вида x != 2
вы не поддерживаете?
Код функционала реализации построения SQL
Что случится, если я напишу Where(x => 2 < x.Age)
?
var name = expField.Member.Name; var prop = CacheTypeReflectionWrapper.GetProps(type).Where(x => x.FieldNameAttributes.Any()).First(x => x.Name.Equals(name));
Эмм. Во-первых, в MemberExpression
может быть не только свойство. Во-вторых, там уже есть MemberInfo
, зачем его где-то искать. В-третьих, если уж вы его где-то ищете, ну возьмите вы словарь (с правильным компарером).
var attrs = prop.FieldNameAttributes; fieldName = attrs.First()
Я даже не буду спрашивать, почему их может быть больше одного.
var unaryNode = left.Right as UnaryExpression; if (unaryNode != null) { expValue = unaryNode.Operand as ConstantExpression; if (expValue != null) { InitParams(command, strBuilder, fieldName, parameter, expValue); } }
Вы никогда не слышали, что бывает унарная операция Not
?
То есть условия вида x != 2 вы не поддерживаете?
Отвечу за автора. Параметр выражения — это всегда объект, представляющий строку таблицы (проекции автором не реализованы). А сравнение строки таблицы с чем бы то ни было целиком бессмысленно.
А сравнение строки таблицы с чем бы то ни было целиком бессмысленно.
Если считать, что проекций нет и не будет, и джойнов тоже никогда не будет...
Пойнт, впрочем, был не в этом, а в том, что есть много разных полезных вещей, которые имеют семантически адекватную конверсию в SQL (начиная с string.StartsWith
), но которые автор не замечает. Хуже того, автор считает, что любой MemberExpression
взят от параметра выражения — что, очевидно, легко опровергается чем-нибудь навроде x.Year == DateTime.Now.Year
.
Что случится, если я напишу Where(x => 2 < x.Age)?
Тут автор не одинок. В языке запросов MS Dynamics CRM (Entity2Crm) все упадет :-)
Готовим ORM, не отходя от плиты. Генерируем SQL — запрос на основе бинарных деревьев выражений