2011-04-15 42 views
3

我試圖對DateTime進行限制的擴展方法?屬性。這是爲了一個搜索查詢,我真的不希望爲所有可能的日期字段複製此代碼。NH QueryOver擴展:如何將成員表達式合併到另一個表達式中?

public static IQueryOver<T, T> WhereInOpenEndedDateRange<T>(this IQueryOver<T, T> query, 
    Expression<Func<object>> field, 
    DateTime? rangeFrom, 
    DateTime? rangeTo) 
{ 
    if(rangeFrom.HasValue && rangeTo.HasValue) 
    { 
     query.WhereRestrictionOn(field).IsBetween(rangeFrom.Value).And(rangeTo.Value); 
    } 
    else if (rangeFrom.HasValue) 
    { 
     //query.Where(() => /* help */ >= rangeFrom.Value); 
    } 
    else if (rangeTo.HasValue) 
    { 
     //query.Where(() => /* help */ <= rangeTo.Value); 
    } 

    return query; 
} 

我想我缺少表達式的一個基本方面。是否有可能傳遞某種形式的Expression參數並將其用於/* help */點?

感謝

更新

越來越近了,但還是覺得這樣很遠很遠......

else if (rangeFrom.HasValue) 
{ 
    var lt = Expression.LessThanOrEqual(field, Expression.Constant(rangeFrom, typeof(DateTime?))); 
    var b = Expression.Lambda<Func<bool>>(lt); 
    query.Where(b); 
} 

但是這不會工作,因爲它會是比較Func<object>DateTime? 。如何將原始屬性表達式合併爲一個新的Func<bool>並保留所需的位以保持NH QueryOver的完整性?

看着NH源QueryOverRestrictionBuilder之後,我會做

string propertyName = ExpressionProcessor.FindMemberExpression(field.Body) 

,並建立與標準方法的限制。

回答

2

嗯,我無法弄清楚如何使用

Expression<Func<bool>> 

簽名要做到這一點,但是這僅僅是對的DateTime?的,無論如何,所以我不認爲我加的限制將如何做出任何區別。

基本上,您需要表達式(您的示例中的字段)與您發送的參數完全匹配,即x => x.SomeNullableDateField。 「x」爲你

session.QueryOver<YourClass>() 

這樣開始了查詢的類型,它需要被列入表達的類型被髮送,也錯過了獲得該參數的持有,使用

ParameterExpression param = expression.Parameters.Single() 

用於構建比較表達式。

您已將二進制表達式轉換爲Expression<Func<bool>>,但您必須進一步將其更改爲Expression<Func<T, bool>>

public static IQueryOver<T, T> WhereInOpenEndedDateRange<T>(this IQueryOver<T, T> query, 
    Expression<Func<T, DateTime?>> expression, 
    DateTime? rangeFrom, 
    DateTime? rangeTo) where T : class 
{ 
    // Lambda being sent in 
    ParameterExpression param = expression.Parameters.Single(); 

    if(rangeFrom.HasValue && rangeTo.HasValue) 
    { 
     // GT Comparison 
     var expressionGT = 
      Expression.GreaterThanOrEqual(
       expression.Body, 
       Expression.Constant(rangeFrom.Value, typeof(DateTime?) 
      ) 
     ); 

     // LT Comparison 
     var expressionLT = 
      Expression.LessThanOrEqual(
       expression.Body, 
       Expression.Constant(rangeTo.Value, typeof(DateTime?) 
      ) 
     ); 

     query.Where(
       Expression.Lambda<Func<T, bool>>(expressionGT, param)) 
       .And(
       Expression.Lambda<Func<T, bool>>(expressionLT, param) 
     ); 
    } 
    else if(rangeFrom.HasValue) 
    { 
     // GT Comparison 
     BinaryExpression expressionGT = 
      Expression.GreaterThanOrEqual(
       expression.Body, 
       Expression.Constant(rangeFrom.Value, typeof(DateTime?) 
      ) 
     ); 

     // covert to lambda 
     query.Where(Expression.Lambda<Func<T, bool>>(expressionGT, param)); 
    } 
    else if(rangeTo.HasValue) 
    { 
     // LT Comparison 
     BinaryExpression expressionLT = 
      Expression.LessThanOrEqual(
       expression.Body, 
       Expression.Constant(rangeTo.Value, typeof(DateTime?) 
      ) 
     ); 

     query.Where(Expression.Lambda<Func<T, bool>>(expressionLT, param)); 
    } 

    return query; 

} 

使用

var test = session.QueryOver<MyPocoClass>() 
      .WhereInOpenEndedDateRange(x=>x.SomeNullableDateField, DateTime.Now, null); 
+0

這使得有很大的意義了。我可以將它重載爲`Expression >`參數。很好的答案。謝謝! – dotjoe 2011-05-24 20:18:27