成员表达式无法从可为空的十进制数转换为对象

jfi*_*204 5 c# asp.net-mvc linq-expressions

我正在处理一个 MVC 项目,并希望将一个属性的名称传递给 Html.TextboxFor 方法。这是我的视图模型

public class RuleViewModel<T> where T : class, IValidatableObject
{
    private T _rule;
    public T RuleModel
    {
        get
        {
            return _rule
                ?? (_rule = Activator.CreateInstance<T>());
        }
    }

    public RuleMetadata Metadata { get; set; }

    public Expression<Func<RuleViewModel<T>, Object>> GetParameterByName(PropertyInfo pi)
    {
        var fieldName = Expression.Parameter(typeof(RuleViewModel<T>), "x");
        var fieldExpression = Expression.PropertyOrField(Expression.Property(fieldName, "RuleModel"), pi.Name);
        var exp = Expression.Lambda<Func<RuleViewModel<T>, Object>>(fieldExpression, fieldName);
        return exp;
    }

}
Run Code Online (Sandbox Code Playgroud)

然后在视图中我这样做

  @foreach (var prop in Model.RuleModel.GetType().GetProperties())
    {
        var result = Model.Metadata.Columns.SingleOrDefault(m => m.ColumnName == prop.Name);
        if (result != null)
        {
            <td>
                @Html.TextBoxFor(Model.GetParameterByName(prop))
            </td>
        }
    }
Run Code Online (Sandbox Code Playgroud)

问题是,当属性的类型为decimal? 时,我得到一个 cannot convert nullable decimal to object 错误。我环顾四周,发现您可以使用 Expression.Convert 来解决此问题,但是当我这样做时,视图出现错误

模板只能用于字段访问、属性访问、单维数组索引或单参数自定义索引器表达式。

任何帮助,将不胜感激。这是我正在进行的概念验证项目,如果没有这件作品,它就会陷入困境。

Mik*_*bel 3

问题是你不能只在调用时使用objectas 。它需要 形式的 lambda 表达式,并且 C# 的方差规则使得 a与 的赋值不兼容。您也不能简单地使用,因为 MVC 内部不会接受主体为TPropertyTextBoxFor<TModel, TProperty>()Func<TModel, TProperty>Func<TModel, decimal?>Func<TModel, object>Convert()Convert

可以做的是使用动态绑定来TextBoxFor<TModel, TProperty>()使用正确的类型参数进行调用:

public Expression GetParameterByName(PropertyInfo pi)
{
    var fieldName = Expression.Parameter(typeof(RuleViewModel<T>), "x");
    var fieldExpression = Expression.PropertyOrField(
        Expression.Property(fieldName, "RuleModel"),
        pi.Name);
    var exp = Expression.Lambda(
        typeof(Func<,>).MakeGenericType(typeof(RuleViewModel<T>), fieldExpression.Type),
        fieldExpression,
        fieldName);
    return exp;
}

// ...

@InputExtensions.TextBoxFor(Html, (dynamic)Model.GetParameterByName(prop))
Run Code Online (Sandbox Code Playgroud)