我想用我自己的方法扩展NHibernate 3的默认LINQ提供程序。我希望能够使用我的POCO中的一些方法。我有一个名为Range的组件,在我的许多POCO中经常使用。这个nhibernate组件类有一个方法Contains(int value)我想在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方法中,我不知道如何访问Range类的Min和Max属性来构建HqlTreeNode
答案 0 :(得分:2)
您可以采用手动方法:最简单的方法是创建一个代表您想要的LINQ树:arguments[0] >= targetObject.Min && arguments[1] <= targetObject.Max
。此处>=
为Expression.GreaterThenOrEqual
,.
为Expression.Property
,依此类推。
当你有一个表达式树时,只需将visitor
应用于它并返回它返回的内容(我不记得确切的API,但如果需要其他帮助,我可以查看它。)
另一种解决方案可能是尝试我的小型图书馆:Expressive
它尝试将方法IL转换为表达式,因此您可以执行LinqToHqlGeneratorsRegistry
或IRuntimeMethodHqlGenerator
尝试内联任何未知属性/方法。
答案 1 :(得分:1)
在这里扩展LINQ提供程序有一些很好的例子:http://www.primordialcode.com/