2012-05-03 32 views
2

對於我正在開發的項目,我必須使用Linq創建一些規範。現在我有一個字典,我必須在其中搜索值。由於NHibernate的默認Linq實現不支持ContainsValue函數,因此我決定創建自己的。Linq到Nhibernate:帶有元素的HqlTreeBuilder如何使用?

所以我創建了一個名爲ContainsValueGenerator類從BaseHqlGeneratorForMethod推導如下:

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?

由於提前, Rob範Pamel

回答

1

的解決方案是創建自己的HqlElements類,從HqlExpression繼承。實際上它只是HqlIndices課程的副本。

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

棘手的部分是將此屬性添加到HqlTreeBuilder類。因此您可以使用擴展方法。這包含一個醜陋的一段代碼,通過反射獲得HqlTreeBuilder的工廠。

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); 
    } 
} 

您的發電機現在可以改爲:

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())); 
    } 
} 

最好的解決辦法是這段代碼將使其成爲NHibernate的本身。也許我會爲GitHub添加一個補丁。

相關問題