转换表达式<func <t,bool?=“”>&gt;到表达式<func <t,bool =“”>&gt; </func <t,> </func <t,>

时间:2013-01-16 10:48:35

标签: asp.net-mvc linq lambda expression

真的很简单。

我有MVC视图,显示Nullable Bool,e,g,

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。

4 个答案:

答案 0 :(得分: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

答案 1 :(得分: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);
    }

答案 2 :(得分:0)

我想仅仅将表达式转换为另一种类型是不够的,MVC使用表达式是有原因的,所以我怀疑它需要检查给定的表达式并在其上应用一些魔法。

您可以创建一个执行转换的新表达式,如下所示:

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

但正如我所说,我怀疑它还不够,MVC可能想要检查表达式中的模型成员等。

答案 3 :(得分:0)

这个怎么样:

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

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

这样你包装原始表达式,你可以转换bool的结果?布尔。

它能解决你的问题吗?