看起来您正在尝试创建一个包含动态数量字段的对象,例如 ViewBag。您不需要为此进行映射。 .NET 已通过 ExpandoObject、DynamicObject 类和dynamic
关键词。
不要构建字段和值的列表,而是创建一个 ExpandoObject 并向其中添加字段,就像使用 ViewBag 一样:
dynamic formData=new ExpandoObject();
formData.Name = "Job blogs";
formData.Date = DateTime.Today;
formData.IsEnabled = true;
formData.Titles = new []{
new SelectedListeItem{Text="Mr",Value="Mr"},
new SelectedListeItem{Text="Mrs",Value="Mrs"}
};
您可以将该对象用作 ViewModel,就像 ViewBag 一样。
// Controller
public ActionResult Index(..)
{
....
View(formData);
}
//View
@model dynamic
<h1>@Model.Name</h1>
更新 - 从字段列表中展开
扩展对象 https://msdn.microsoft.com/en-us/library/system.dynamic.expandoobject(v=vs.110).aspx实施IDictionary<string, object>
显式地,这意味着人们可以在运行时不知道其编号或名称的情况下进行属性,例如:
var fields = new (string name,object value) []
{
("Name","Job blogs"),
("Date", DateTime.Today),
("IsEnabled",true)
};
dynamic viewModel=new ExpandoObject();
var dict=(IDictionary<string,object>)viewModel;
foreach(var field in fields)
{
dict.Add(field.name,field.value);
}
我使用元组语法只是为了避免重复输入表单字段
更新 2 - 具有字典存储的强类型类
正如 Stephen Muecke 所评论的,使用动态类进行绑定和验证更加困难。另一方面,如果预先知道这些字段,为什么要使用映射或反射呢?
我们可以创建一个 ViewModel 类,它接受一些字段,将它们转换为字典(类似于 ExpandoObject 的做法),并使用字典作为属性的后备存储。
借助 CallMemberName 属性等 C# 魔法,额外的代码就很少了。那里is字典查找的运行时惩罚,只有在存在以下情况时才变得明显lot读/写次数:
class MyViewModel
{
Dictionary<string,object> _dict=new Dictionary<string,object>();
//Get helper
private T getter<T>([CallerMemberName]string name=null)
{
return _dict.TryGetValue(name,out object value)
? (T)Convert.ChangeType(value,typeof(T))
: default(T);
}
private void setter(object value,[CallerMemberName]string name=null)
{
_dict[name]=value;
}
public DateTime Date {
get => getter<DateTime>();
set => setter(value);
}
public string Name {
get => getter<string>();
set => setter(value);
}
public bool IsEnabled {
get => getter<bool>();
set => setter(value);
}
public MyViewModel(IEnumerable<FormField> fields)
{
_dict=fields.ToDictionary(
field=>field.FieldName,
field=>(object)field.FieldValue);
}
}
....
var formData = new [] {
new FormField { FieldName = "Date", FieldValue = "2017-09-14" },
new FormField { FieldName = "Name", FieldValue = "Job blogs" },
new FormField { FieldName = "IsEnabled", FieldValue = "true" }
};
var myViewModel = new MyViewModel(formData);
每个属性的设置器仅使用属性名称作为键来设置字典值。吸气剂使用CallerMemberName
获取属性的名称并将其用作密钥