NHibernate 3-扩展Linq提供程序BaseHqlGeneratorForMethod.BuildHql问题 [英] NHibernate 3 - extending Linq provider BaseHqlGeneratorForMethod.BuildHql problem

查看:99
本文介绍了NHibernate 3-扩展Linq提供程序BaseHqlGeneratorForMethod.BuildHql问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想用自己的方法扩展NHibernate 3的默认LINQ提供程序.我希望能够使用我的POCO中的某些方法.我有一个名为Range的组件,在我的许多POCO中都经常使用它.这个nhibernate组件类有一个我想在LINQ查询表达式中使用的方法Contains(int value)

I want to extend the default LINQ provider for NHibernate 3 with methods of my own. I want to be able to use some methods from my POCOs. I have a component named Range which is used quite often in many of my POCOs. This nhibernate component class has a method Contains(int value) that I want to use in LINQ query expressions

映射:

<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提供程序,但是我不知道如何构建使其工作所需的表达式.

I looked at several blog posts explaining how to extend the LINQ provider but I don't know how to build the expressions required for this to work.

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

In the BuildHql method I don't know how to access Min and Max properties of my Range class to build a HqlTreeNode

推荐答案

  1. 您可以使用手动方法:最简单的方法是创建一个代表您想要的内容的LINQ树:arguments[0] >= targetObject.Min && arguments[1] <= targetObject.Max.在这里>=Expression.GreaterThenOrEqual.Expression.Property,依此类推.

  1. You can a manual approach: the easiest way is to create a LINQ tree that represents what you want: arguments[0] >= targetObject.Min && arguments[1] <= targetObject.Max. Here >= is Expression.GreaterThenOrEqual, . is Expression.Property and so on.

当您拥有表达式树时,只需对它应用visitor并返回它返回的内容(我不记得确切的API,但是如果需要其他帮助,我可以调查一下它).

When you have an expression tree, just apply visitor to it and return what it returns (I do not remember the exact API, but I can look into it if additional help is needed).

另一个解决方案可能是尝试我的小图书馆:富有表现力.
它尝试将方法IL转换为表达式,因此您可以执行LinqToHqlGeneratorsRegistryIRuntimeMethodHqlGenerator尝试内联 any 未知属性/方法.

Another solution may be to try my little library: Expressive.
It attempts to convert method IL into expressions, so you could do a LinqToHqlGeneratorsRegistry or IRuntimeMethodHqlGenerator that tries to inline any unknown property/method.

这篇关于NHibernate 3-扩展Linq提供程序BaseHqlGeneratorForMethod.BuildHql问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆