问题描述
我的问题类似于this question,但不是通过反射将Data Annotations应用于属性Name(由ModelMetadata.DisplayName处理),而是将其应用于值(未由ModelMetadata处理)。
详细说明
在ASP.NET MVC程序的上下文中。
假设我有一个Model类
public class Model
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string NickName { get; set; }
public string Address { get; set; }
public int Phone { get; set; }
[Display(Name = "Start Date")]
[DataType(DataType.Date)]
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:dd/MM/yyyy}")]
public DateTime StartDate { get; set }
[Display(Name = "End Date")]
[DataType(DataType.Date)]
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:dd/MM/yyyy}")]
public DateTime EndDate { get; set }
}
然后,假设该模型至少在5个不同的 View 中使用,其中每个属性的值都必须完整显示。 (有时是每个实例,有时是少数,有时是一个)。
我可以在自己的列表中手动列出每个媒体资源访问权限
<td>@Html.DisplayFor(item.<Property>)</td>
对于每个 View 。但是,如果稍后将模型的定义扩展为包括新的属性(例如“描述,关系和可靠性”),那将无济于事。然后,我需要手动更新每次出现的完整Model list 。
我可以使用反射来遍历PropertyInfo的列表,并节省使用以下方法手动列出每个属性的麻烦:
<td>@property.GetValue(item)</td>
但是
DisplayFor(x)
不支持像x=>property.GetValue(item)
这样复杂的表达式,而这个意味着我丢失了将DateTime格式化为的数据注释01/01/1990
代替01-Jan-90 12:00:00 AM
并且可能还会导致所有类型的注释(包括验证)丢失。问题解决方案
到目前为止,我已经考虑(并在某些情况下尝试过)以下解决方案:
@property.GetValue(item)
功能的表达式[编辑]
DisplayFor(x => property.GetGetMethod())
以及在x上对其进行编码的.Invoke
。[/编辑]
最后的解决方案将打破
@Html.DisplayFor(m=>property.GetValue(item)
进入理论上的工作@Html.DisplayFor(m=>item.Properties[i].Value)
除了通过(.Value)获取名称为Name(Properties [“Name”])的属性有点不直观的需求之外,这似乎是最可行的解决方案,但要以模型清晰为代价。[编辑]
最近,我创建了一个Utility方法,该方法从PropertyInfo中检索DisplayFormatAttribute,如果未注释格式字符串,则返回DisplayFormatString或默认值“{0}”。然后,我用它在ViewModel中创建了一组预格式化的属性值。
就目前而言,这似乎是我所知道的最优雅的方法,即在仍从 View 中检索必要数据的同时,尽可能地将 View 与模型分离。
[/编辑]
问题
目前,这纯粹是一种学习练习,但我想知道...
如果我失败了,并且都拥有我的Reflection蛋糕并且也吃了Data Annotations,是否有可能成功?还是我必须寻求替代解决方案?
如果我必须寻求替代解决方案,是我错过了某些路线,还是至少在正确的轨道上?
最佳答案
也许类似于:
@foreach (var property in Model.GetType().GetProperties())
{
<li>@property.GetValue(Model, null)</li>
}