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

5

我正在进行一个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;
    }

}

然后在视图中我这样做

  @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>
        }
    }

问题在于,当属性为decimal?类型时,我会得到一个无法将可空的decimal转换为对象的错误。我看了一下发现可以使用Expression.Convert来解决这个问题,但是当我这样做时,视图上会出现错误。
模板只能与字段访问、属性访问、单维数组索引或单参数自定义索引器表达式一起使用。
任何帮助都将不胜感激。这是我正在开发的一个概念证明项目,如果没有这个部分,它就无法继续进行了。
1个回答

3
问题在于在调用 TextBoxFor<TModel, TProperty>()时,你不能仅将object作为TProperty使用。它需要一个形如 Func<TModel, TProperty> 的 lambda 表达式,而 C# 的可变性规则是这样的,即 Func<TModel, decimal?>Func<TModel, object> 不兼容。你也不能简单地使用 Convert(),因为MVC内部不接受其主体为 Convert 表达式的 lambda。
你可以使用动态绑定来调用带有正确类型参数的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))

谢谢您的帮助。当我这样做时,我会得到一个运行时错误,说没有适用的方法名为'TextBoxFor',但似乎有一个同名的扩展方法。扩展方法无法动态调度。有什么想法吗?我能够通过定义四五个不同的GetParameter方法,并在视图中使用条件语句来解决整个问题,这对于概念验证来说是可行的,但它真的很丑陋。 - jfin3204
如果您静态调用 TextBoxFor() 会怎样呢?请尝试以下代码:@InputExtensions.TextBoxFor(Html, (dynamic)Model.GetParameterByName(prop)),看看是否可行。 - Mike Strobel
马克,你是一个帅气的男人。这就解决了问题。非常感谢你。 - jfin3204

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接