我正在研究MVC项目,并希望将
Html.TextboxFor方法传递给属性的名称.这是我的viewmodel
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>
}
}
问题是,当属性是十进制类型?时,我得到一个无法将可空小数转换为对象错误.我环顾四周,发现你可以使用Expression.Convert来解决这个问题,但是当我这样做时,我在视图上出现错误
模板只能用于字段访问,属性访问,单维数组索引或单参数自定义索引器表达式.
任何帮助,将不胜感激.这是我正在研究的概念证明项目,如果没有这件作品,它就已经死了.
最佳答案 问题是,在调用TextBoxFor< TModel,TProperty>()时,不能只将对象用作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))