2012-05-03 6 views
2

私が開発しているプロジェクトでは、Linqを使用していくつかの仕様を作成する必要があります。今私は値を検索しなければならない辞書があります。 NHibernateのデフォルトのLinq実装はContainsValue関数をサポートしていないので、自分で作成することにしました。LinqにNhibernateするには:HqlTreeBuilder with Elementsどのように使用するのですか?

だから私は、次のようにBaseHqlGeneratorForMethod由来ContainsValueGeneratorという名前のクラスを作成しました:

public class ContainsValueGenerator : BaseHqlGeneratorForMethod 
{ 
    public ContainsValueGenerator() 
    { 
     SupportedMethods = new[] { ReflectionHelper.GetMethodDefinition(() => new Dictionary<object, object>().ContainsValue(null)) }; 
    } 

    public override HqlTreeNode BuildHql(MethodInfo method, Expression targetObject, ReadOnlyCollection<Expression> arguments, HqlTreeBuilder treeBuilder, IHqlExpressionVisitor visitor) 
    { 
     //Session.CreateQuery("from Message m where 'aDictionaryValue' in elements(m.Dictionary)"); 

     HqlTreeNode hqlTreeNode = treeBuilder.Elements(); // TODO include dictionary here? 
     return treeBuilder.In(visitor.Visit(arguments[0]).AsExpression(), hqlTreeNode); 
     //return treeBuilder.In(visitor.Visit(arguments[0]).AsExpression(), treeBuilder.Indices(visitor.Visit(targetObject).AsExpression())); ContainsKey Method implementation 
    } 
} 

私はNHibernateのからソースコードを見て、にContainsKeyメソッドの実装を取りました。 HqlsyntaxはContainsKey構文と非常によく似ています。変更する必要があるのは、treebuilder.Indices()の代わりに、treebuilder.Elements(コメントに表示)を使用する必要があります。

これは私が立ち往生している場所です。私は自分の辞書でElementsExpressionを提供することはできません。 要素式を利用するHqlTreeNodeを作成するにはどうすればよいですか?事前に

おかげで、 ロブ・ヴァン・Pamel

答えて

1

ソリューションはHqlExpressionから継承し、独自のHqlElementsクラスを作成することです。実際、それはHqlIndicesクラスの単なるコピーです。

public class HqlElements : HqlExpression 
{ 
    public HqlElements(IASTFactory factory, HqlExpression dictionary) 
     : base(HqlSqlWalker.ELEMENTS, "elements", factory, dictionary) 
    { 
    } 
} 

トリッキーな部分は、これをプロパティとしてHqlTreeBuilderクラスに追加することです。したがって、拡張メソッドを使用することができます。これには1つのuglyコードが含まれています。リフレクションを使用してHqlTreeBuilderのファクトリを取得します。コードのこの作品は、NHibernateは自分自身にそれを作るということだろう

public class ContainsValueGenerator : BaseHqlGeneratorForMethod 
{ 
    public ContainsValueGenerator() 
    { 
     SupportedMethods = new[] { ReflectionHelper.GetMethodDefinition(() => new Dictionary<object, object>().ContainsValue(null)) }; 
    } 

    public override HqlTreeNode BuildHql(MethodInfo method, Expression targetObject, ReadOnlyCollection<Expression> arguments, HqlTreeBuilder treeBuilder, IHqlExpressionVisitor visitor) 
    { 
     return treeBuilder.In(visitor.Visit(arguments[0]).AsExpression(), treeBuilder.Elements(visitor.Visit(targetObject).AsExpression())); 
    } 
} 

最適なソリューション:

public static class HqlTreeBuilderExtensions 
{ 
    public static HqlElements Elements(this HqlTreeBuilder treeBuilder, HqlExpression dictionary) 
    { 
     var factory = (IASTFactory) treeBuilder.GetType().GetField("_factory", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(treeBuilder); 

     return new HqlElements(factory, dictionary); 
    } 
} 

あなたの発電機は今に変更することができます。たぶん、GitHubにパッチを追加します。

関連する問題