NHibernate 3 - расширение поставщика Linq BaseHqlGeneratorForMethod.BuildHql проблема
Я хочу расширить поставщика LINQ по умолчанию для NHibernate 3 с помощью моих собственных методов. Я хочу иметь возможность использовать некоторые методы из моих POCO. У меня есть компонент под названием Range, который часто используется во многих моих POCO. Этот класс компонента nhibernate имеет метод Contains(значение int), который я хочу использовать в выражениях запросов LINQ.
Отображение:
<class name="Foo">
...
<component name="AgeRange">
<property name="Min" column="age_min" />
<property name="Max" column="age_max" />
</component>
</class>
Учебный класс
public class Range {
public int Min { get; set; }
public int Max { get; set; }
public bool Contains(int value) {
return value >= this.Min && value <= this.Max;
}
}
// this is the LINQ query I want to be able to write
// which will generate 'SELECT * FROM Foo WHERE 25 BETWEEN age_min AND age_max'
var s = from x in session.Query<Foo> where x.AgeRange.Contains(25) select x;
// I know the following works
var s = from x in session.Query<Foo> where x.AgeRange.Min <= 25 && x.AgeRange.Max >= 25 select x;
Я просмотрел несколько постов в блоге, объясняющих, как расширить поставщика LINQ, но я не знаю, как создать выражения, необходимые для этого.
public class RangeContainsGenerator : BaseHqlGeneratorForMethod
{
public MemberInfo RangeMin;
public MemberInfo RangeMax;
public RangeContainsGenerator() {
SupportedMethods = new[] {
ReflectionHelper.GetMethodDefinition<Range>(x=> x.Contains(0)),
};
RangeMin = ReflectionHelper.GetProperty<Range, int>(x => x.Min);
RangeMax = ReflectionHelper.GetProperty<Range, int>(x => x.Max);
}
public override NHibernate.Hql.Ast.HqlTreeNode BuildHql(
System.Reflection.MethodInfo method,
System.Linq.Expressions.Expression targetObject,
System.Collections.ObjectModel.ReadOnlyCollection<System.Linq.Expressions.Expression> arguments,
NHibernate.Hql.Ast.HqlTreeBuilder treeBuilder,
NHibernate.Linq.Visitors.IHqlExpressionVisitor visitor) {
// The targetObject parameter contains the "Foo.AgeRange" member access expression
throw new NotImplementedException();
}
}
В методе BuildHql я не знаю, как получить доступ к свойствам Min и Max моего класса Range, чтобы построить HqlTreeNode
2 ответа
Вы можете использовать ручной подход: самый простой способ - создать дерево LINQ, которое представляет то, что вы хотите:
arguments[0] >= targetObject.Min && arguments[1] <= targetObject.Max
, Вот>=
являетсяExpression.GreaterThenOrEqual
,.
являетсяExpression.Property
и так далее.Когда у вас есть дерево выражений, просто примените
visitor
и вернуть то, что он возвращает (я не помню точный API, но я могу изучить его, если потребуется дополнительная помощь).Другое решение может быть попробовать мою маленькую библиотеку: Expressive.
Он пытается преобразовать метод IL в выражения, чтобы вы могли сделатьLinqToHqlGeneratorsRegistry
или жеIRuntimeMethodHqlGenerator
который пытается встроить любое неизвестное свойство / метод.
Вот несколько хороших примеров расширения поставщика LINQ здесь: http://www.primordialcode.com/