【发布时间】:2017-05-09 01:31:13
【问题描述】:
问题描述
我的问题类似于this question,但不是通过反射将数据注释应用于属性名称(由 ModelMetadata.DisplayName 处理),而是将它们应用于值(不由 ModelMetadata 处理)。
详细说明
在 ASP.NET MVC 程序的上下文中。
假设我有一个模型类
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 个不同的视图中,其中每个属性的值都必须完整显示。 (有时是每个实例,有时是少数,有时是一个)。
我可以手动列出每个属性的访问权限<td>@Html.DisplayFor(item.<Property>)</td>
每个视图。
但是,如果稍后模型的定义扩展为包含新属性(例如描述和关系以及可靠性),那将无济于事。然后我需要手动更新每次出现的完整模型列表。
我可以使用反射来遍历 PropertyInfo 的列表,并且不必使用手动列出每个属性<td>@property.GetValue(item)</td>
但是DisplayFor(x) 不支持像x=>property.GetValue(item) 这样复杂的表达式,并且这 意味着我丢失了将日期时间格式化为01/01/1990
的数据注释
而不是01-Jan-90 12:00:00 AM
并且可能还会导致丢失所有类型的注释,包括验证。
问题解决方案
到目前为止,我已经考虑过(并且在某些情况下尝试过)以下解决方案:
-
[失败] 手动制作模拟
@property.GetValue(item)功能的表达式
[编辑] -
[失败] 传递 DisplayFor 一个 MethodInfo 对象,表示属性访问器
DisplayFor(x => property.GetGetMethod())以及在 x 上.Invokeing 它。
[/Edit] - 正常手动检索值,然后
- 按照this question 的建议,在插入视图元素之前对其执行一个方法来手动检索和实施注释数据,或者
- 根据需要在显示模板视图中重新实现 DisplayFor 处理数据注释,并按照 this question 的建议通过 DisplayFor 将其直接应用于值
- 重构 Model 类以仅包含“Prop”实例的列表(SortedList?),其中“Prop”是表示具有 Name 和 Value 元素的 Property 的类。
这最后的解决方案会破坏@Html.DisplayFor(m=>property.GetValue(item)
变成理论上可行的@Html.DisplayFor(m=>item.Properties[i].Value)
除了需要通过 (.Value) 获取名为 Name (Properties["Name"]) 的属性有点不直观之外,这似乎是最可行的解决方案,但以模型清晰度为代价。
[编辑]
最近,我创建了一个实用程序方法,该方法从 PropertyInfo 中检索 DisplayFormatAttribute,如果格式字符串未注释,则返回 DisplayFormatString 或默认值“{0}”。然后,我使用它在 ViewModel 中创建了一组预格式化的属性值。
目前看来,这是我所知道的最优雅的方式,可以将视图与模型尽可能多地分离,同时仍从中检索必要的数据。
[/Edit]
问题
目前,这纯粹是一个学习练习,但我想知道...
是否有可能在我失败的地方取得成功,并且都有我的反射蛋糕并吃掉数据注释?还是我必须寻求替代解决方案?
如果我必须寻求替代解决方案,是否有我错过的路线,或者我至少在正确的轨道上?
【问题讨论】:
-
用自定义属性装饰您的模型,并编写代码来说明如何渲染每个模型。你为什么要这样做
-
正如我所说,这纯粹是一种教育练习。我正在从一个教程构建一个简单的项目,以熟悉 MVC 工作原理的 ASP.NET 版本,然后我想“如果使用 MVC 的全部目的是分离关注点,为什么视图必须对每一个单独的模型上的属性名称,而从概念上讲,他们想要做的只是“显示所有属性的值,或某些生成的属性子集”?”所以我决定看看我能不能做到这一点。
-
我建议的两个解决方案实际上是通过各种方式自己实现格式设置,(尽管使用自定义属性与数据注释存在相同的问题,因为它们不容易通过 PropertyInfo 访问)...但如果可能的话,我宁愿避免在这个意义上重新发明轮子,因为 Html webhelper 模板已经为直接属性访问定义了所有这些功能。
-
它没有深入的知识——只是从模型中读取。当然总会有一些耦合,否则类本身不会很有用。这个想法是最小化耦合,而不是完全删除它。但是有这种想法对你有好处。
-
谢谢。最小化耦合正是我试图通过迭代由其他地方的逻辑创建的集合来替换显式名称引用来实现的目标。
标签: c# asp.net-mvc reflection data-annotations