NHibernate 3 - расширение поставщика Linq для BaseHqlGeneratorForMethod.BuildHql - PullRequest
4 голосов
/ 12 октября 2010

Я хочу расширить поставщика 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 ]

2 голосов
/ 31 мая 2011
  1. Вы можете использовать ручной подход: самый простой способ - создать дерево LINQ, которое представляет то, что вы хотите: arguments[0] >= targetObject.Min && arguments[1] <= targetObject.Max. Здесь >= равно Expression.GreaterThenOrEqual, . равно Expression.Property и т. Д.

    Если у вас есть дерево выражений, просто примените к нему visitor и верните то, что оно возвращает (я не помню точный API, но могу посмотреть, если потребуется дополнительная помощь).

  2. Другим решением может быть попытка моей маленькой библиотеки: Выразительный .
    Он пытается преобразовать метод IL в выражения, чтобы вы могли сделать LinqToHqlGeneratorsRegistry или IRuntimeMethodHqlGenerator, который пытается встроить любое неизвестное свойство / метод.

1 голос
/ 22 октября 2010

Вот несколько хороших примеров расширения поставщика LINQ: http://www.primordialcode.com/

...