不能使用foreach迭代ViewModel

本文关键字:迭代 ViewModel foreach 不能 | 更新日期: 2023-09-27 18:22:11

我创建了一个ViewModel文件:

public class MyViewModel
{
    public string AString { get; set; }
    public string BString { get; set; }
    public string CString { get; set; }
    public string DString { get; set; }
    public DateTimeOffset ADate { get; set; }
    public DateTimeOffset BDate { get; set; }
}

我试图运行一个for each语句来迭代项目,但我得到了

MyViewModel不包含GetEnumerator 的公共定义

以下是我尝试使用它的声明:

public ActionResult MyMethod(MyViewModel model)
{
    foreach(var item in model)
    {
        //add code here
    }
}

我不知道为什么会发生这种事,有人能帮忙吗?

编辑:ViewModel正在接受通过AJAX get调用传递给它的数据。我只是根据需要填写字段。我这样做是因为我不想有一个可以接受20多个内联参数(字符串a、字符串b、字符串c…)的方法。制作一个包含所有可能字段的ViewModel更有意义,AJAX调用会相应地填充这些字段。之后我想做的是将这些值传递到服务中,但必须对它们进行一些更改才能使用旧服务。

服务期望:

serviceName(ID, GUID, NAME, parameters)
ID - string
GUID - GUID
NAME - string
parameters - new parameter { name = "[model.Name]", value = new List<string>(){ "[model.value]" }}

[model.Name]和[model.Value]是通过在我创建的模型中迭代"如果使用正确的术语"来填充的。

不能使用foreach迭代ViewModel

以下是您可以使用反射来循环遍历模型中的所有公共属性:

var properties = typeof(MyViewModel).GetProperties();
foreach(var property in properties) 
{
    var propertyName = property.Name;
    var propertyValue = property.GetValue(model);
    //Now process the property
}

然而,请注意,这种反映会对性能造成影响,如果有更好的替代方案,则不应使用。在您的情况下,看起来您可以很好地声明几个数组或字典来存储数据。例如:

public class MyViewModel
{
    public MyViewModel
    {
        TheStrings = new string[4];
        TheDates = new DateTimeOffset[2];
    }
    public string TheStrings { get; private set; }
    public DateTimeOffset TheDates { get; private set; }
}

现在您可以访问model.TheStrings[0]而不是model.AString,依此类推;使用带有关键字a、B、C、D的字典可以进一步提高可读性,但想法是一样的。现在,您可以轻松地foreach您的字符串和日期。

foreach适用于任何实现IEnumerable和数组的对象集合。在您的代码中,MyViewModel是一个没有实现Innumerable的POCO类。

如果您发布的模型是MyViewModel的集合,则可以循环使用这些模型。例如,如果你发布了一份客户/产品列表,你会做这样的

public ActionResult MyMethod (IEnumerable<MyViewModel> model)
{
  foreach(var product in model)
  {
    //You can access each property here
   //product.AString
  }
}

如果您只是想读取发布模型的不同属性值,则不需要foreach。简单地,读取每个属性

public ActionResult MyMethod(MyViewModel model)
{
  var aStringVal =  model.AString;
  var bStringVal = model.BString;
  //Do something with the values.
}

如果你仍然想获得MyViewModel的单个实例的所有属性,你应该使用反射来获得,正如Konamiman在他的回答中所写的那样。

C#与JavaScript:完全不同

  • 在C#中,foreach循环遍历对象序列(IEnumerable)中的每个对象

  • 在JavaScript中,foreach循环遍历单个对象中每个属性的值。

在C#中,您不能轻松地循环遍历类中的每个属性,也不应该尝试这样做。
相反,如果您想要多个相同类型的属性,请使用List<T>

public class MyViewModel
{
    public List<string>   MyStrings { get; set; }
    public List<DateTime> MyDates   { get; set; }
}
foreach (string s in model.MyStrings)
{
}
foreach (DateTime d in model.MyDates)
{
}

基于添加到问题的更新信息

如果参数可以在每次调用时更改,那么使用具有固定属性的视图模型将不适合您的情况。

记住,C#是强类型的,你不能只发送你想要的任何值,只能发送已经定义的值。

如果每次调用的参数都可以更改,那么就不能使用固定的视图模型,所以将方法更改为名称+值的字典:

 public ActionResult MyMethod(IDictionary<string, string> model)
 {
     var parameters = new List<Parameter>();
     foreach (var kvp in model)
     {
         parameters.Add(new parameter { name = kvp.Key, value = new List<string> { key.Value }});
     }

如果你有很多价值观,这可能也很合适。

您可以使用继承或具有dictionary属性的ViewModel,但这是的重要部分


如果参数始终相同,则明确使用值:

 public ActionResult MyMethod(IDictionary<string, string> model)
 {
     var parameters = new List<Parameter>();
     parameters.Add(new parameter { name = "AString", value = new List<string> { model.AString }});
     parameters.Add(new parameter { name = "BString", value = new List<string> { model.BString }});

但最有可能的情况是客户端正在定义参数。