2013-01-16 83 views
2

簡單的問題真的。轉換表達<Func鍵<T, bool?>>以表達<Func鍵<T, bool>>

我有一個顯示可空布爾,E,G MVC視圖,

Html.CheckBoxFor(model=>model.NullableBoolHere, Model.NullableBoolHere, 

,我想創建一個新的HTML輔助,將接受這種類型的,然後轉換

Null || False => False 
True => True 

所以我必須感謝,我明白,我將不得不使用遞歸以下

public static MvcHtmlString CheckBoxFor<TModel>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, bool?>> expression, object htmlAttributes, bool disabled) 
    { 
     IDictionary<string, object> values = new RouteValueDictionary(htmlAttributes); 

     if (disabled) 
      values.Add("disabled", "true"); 

     Expression<Func<TModel, bool>> boolExpression = CONVERT_TO_BOOL_HERE(expression); 


     return htmlHelper.CheckBoxFor(expression, values); 
    } 

任何幫助複製表達式,但不知道如何去瀏覽表達式本身,找到bool ?,轉換爲bool。

回答

1

所以,最終,我能找到的唯一方法就是解決布爾問題?成布爾自己,然後通過傳遞正確的名稱等

這樣確實一種享受,雖然返回一個「正常」的複選框,這樣都好。如果你確實知道獲取正確ParameterName的更好方法,那聽起來會很棒。

public static MvcHtmlString CheckBoxFor<TModel>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, bool?>> expression, object htmlAttributes, bool disabled) 
    { 
     IDictionary<string, object> values = new RouteValueDictionary(htmlAttributes); 

     if (disabled) 
      values.Add("disabled", "true"); 

     //Compile the expression to get the value from it. 
     var compiled = expression.Compile().Invoke(htmlHelper.ViewData.Model); 
     bool checkValue = compiled.HasValue ? compiled.Value : false; //evaluate the compiled expression 

     //Get the name of the id we should use 
     //var parameterName = ((MemberExpression)expression.Body).Member.Name; // only gives the last part 
     string parameterName = expression.Body.ToString().Replace("model.", "");//.Replace(".", HtmlHelper.IdAttributeDotReplacement); 

     //Return our 'hand made' checkbox 
     return htmlHelper.CheckBox(parameterName, checkValue, values); 
    } 
+0

也可能的語法:var b = e.Compile()(htmlHelper.ViewData.Model);無需使用Invoke – Karl

0

我想這不會是不夠的,只是表達轉換爲另一種類型,MVC使用是有原因的表情,所以我懷疑它需要檢查給定的表達和運用它的一些魔術。

您可以創建一個新的表達式執行轉換,這樣的:

Expression<Func<TModel, bool>> boolExpression = 
     T => expression.Compile()(T).GetValueOrDefault(false); 

但正如我所說,我懷疑這是不夠的,MVC可能要檢查的表達式內部模型成員等。

+0

是的,我得到一個錯誤,如預期。 MVC需要'閱讀'未編譯的表達式來做'魔術'! 「模板只能用於字段訪問,屬性訪問,單維數組索引或單參數自定義索引器表達式。」 – adudley

0

如何:

Expression<Func<TModel, bool>> boolExpression = model => 
     { 
      bool? result = expression.Compile()(model); 

      return result.HasValue ? result.Value : false; 
     }; 

這樣,你包裝了原始的表達,可以將結果從布爾轉換?布爾。

它解決了你的問題嗎?

1

您可以使用此代碼:

var body = Expression.Coalesce(expression.Body, Expression.Constant(false)); 
var boolExpression = (Expression<Func<TModel, bool>>) 
    Expression.Lambda(body, expression.Parameters.First()); 

的優勢,其他的答案是,它不會編譯第一個表達式,它只是包裝它。由此產生的表達類似於此代碼創建的表達式:

m => m.NullableBoolHere ?? false 

Check it live

+0

我喜歡你在這裏做的,很有道理。似乎下面這個我然後打一個MVC問題,我得到的錯誤「模板只能用於字段訪問,屬性訪問,單維數組索引或單參數自定義索引器表達式。」但我會玩這個,看看會發生什麼。謝謝 – adudley

+0

@adudley:在這種情況下,MVC引擎會限制它允許的表達式,因爲它實際上不會執行它們,而是解析它們並根據解析的表達式樹生成一些代碼。爲了保持解析邏輯相對簡單,它對那些表達式中實際允許的內容施加了嚴格的限制。你最好在模型中創建一個包含'NullableBoolHere'的屬性。 –

相關問題