想法(简化)是在字典中包含的ViewModel中具有用户可定义的属性。这些方面的东西:
public class MyViewModel
{
[Required]
public string Name { get; set; }
[DisplayName("User address")]
public string Address { get; set; }
// ...
public IDictionary<string, string> MetaData { get; set; }
}
假设MetaData包含几个额外的属性:PhoneNumber
,Email
等,您可以使用myViewModel.MetaData["PhoneNumber"]
进行访问。
我想要做的是能够在View端的Html助手中使用那些额外的MetaData 属性,就像我使用普通属性一样。
因此,除了使用标准属性:
Html.TextBox("Name")
我还想使用这些附加属性:
Html.TextBox("PhoneNumber")
我的研究让我继承自DataAnnotationsModelMetadataProvider
(因为它还需要支持标准属性的标准DataAnnotations属性)并试图找出究竟要覆盖的内容以便注入附加属性作为额外的ModelMetadata元素,但我有点卡住了。
我是在正确的道路上吗?任何可以帮助我的额外指针?
由于
答案 0 :(得分:2)
另一种选择可能是构建一个类似于MVC 3中的ViewBag / ViewData的动态对象。你可以通过Model.MetaData.Foo
访问一个对象,而Foo
实际上会映射到一个键你的字典。
支持ViewBag对象的类型是System.Web.Mvc.DynamicViewDataDictionary;这个类是内部和密封的,所以你必须自己实现它(除非有一个我不知道的更好的选项)。快速浏览一下MVC 3源代码就可以了:
internal sealed class DynamicViewDataDictionary : DynamicObject {
private readonly Func<ViewDataDictionary> _viewDataThunk;
public DynamicViewDataDictionary(Func<ViewDataDictionary> viewDataThunk) {
_viewDataThunk = viewDataThunk;
}
private ViewDataDictionary ViewData {
get {
ViewDataDictionary viewData = _viewDataThunk();
Debug.Assert(viewData != null);
return viewData;
}
}
// Implementing this function improves the debugging experience as it provides the debugger with the list of all
// the properties currently defined on the object
public override IEnumerable<string> GetDynamicMemberNames() {
return ViewData.Keys;
}
public override bool TryGetMember(GetMemberBinder binder, out object result) {
result = ViewData[binder.Name];
// since ViewDataDictionary always returns a result even if the key does not exist, always return true
return true;
}
public override bool TrySetMember(SetMemberBinder binder, object value) {
ViewData[binder.Name] = value;
// you can always set a key in the dictionary so return true
return true;
}
}
此解决方案相对于修改ModelMetadataProvider的一个可能的优势是,您不必花时间为您的方案构建所有自定义组件 - 默认提供程序应就足够了。