【问题标题】:Is it possible to iterate on List<dynamic>?是否可以在 List<dynamic> 上进行迭代?
【发布时间】:2013-08-13 00:31:08
【问题描述】:

在过去的几天里,我一直在尝试找到一种方法来迭代 List&lt;dynamic&gt;,但没有取得多大成功。

这就是我正在做的:

while (dr.Read())
{
    dynamic e = new ExpandoObject();
    var d = e as IDictionary<string, object>;
    for (var i = 0; i < dr.FieldCount; i++)
        d.Add(dr.GetName(i), DBNull.Value.Equals(dr[i]) ? null : dr[i]);

    result.Add(e);
}

上面的代码是一个返回 IEnumerable&lt;dynamic&gt; 的方法,然后在我的控制器中我正在获取数据:

dynamic irionErrorsExport = oracleDbManager.GetStrCtrlNDGWithErrors(tableName, queryParamsList, periodo, "", "", "");

现在我被困住了,因为我需要迭代 irionErrorsExport 并创建一个“具体”对象以与 EPPlus 一起使用。

谁能告诉我这是否可能并举一个简单的例子?

【问题讨论】:

  • GetStrCtrlDGWithErrors() 是您的方法包含第一个 sn-p 代码吗?
  • 向我们展示GetStrCtrlDGWithErrors 方法签名
  • 请注意,您可以这样做:IDictionary&lt;string, object&gt; e = new ExpandoObject(),将d.* 更改为e.*,然后更改result.Add(e),无需中间转换。

标签: c# dynamic


【解决方案1】:

是的,您可以遍历 dynamic 对象:

dynamic source = new List<int>() {1, 2, 3, 4, 5, 6};
foreach (var item in source)
{
    Console.Write(item.ToString());
}

123456 打印到控制台。

但是,如果无法迭代,则会导致运行时异常:

考虑以下代码:

dynamic source = 2;
foreach (var item in source)
{
    Console.Write(item.ToString());
}

RuntimeBinderException 被抛出:

无法将类型“int”隐式转换为“System.Collections.IEnumerable”

编辑:您应该注意普通变量上的foreachdynamic 之间的区别。它们在另一个 SO 问题中进行了解释:C# 4.0 'dynamic' and foreach statement

【讨论】:

    【解决方案2】:

    如果您像here 一样填充DataTable,您可以使用Json.Net 并轻松获得一个具体 对象

    //Sample DataTable
    DataTable dt = new DataTable();
    dt.Columns.Add("IntCol");
    dt.Columns.Add("StrCol");
    dt.Rows.Add(new object[]{1,"1"});
    dt.Rows.Add(new object[]{2,"2"});
    
    var jsonstr = JsonConvert.SerializeObject(dt);
    var list = JsonConvert.DeserializeObject<List<YourClass>>(jsonstr);
    
    public class YourClass
    {
        public int IntCol { set; get; }
        public string StrCol { set; get; }
    }
    

    【讨论】:

      【解决方案3】:
      while (dr.Read())
      {
          IDictionary<string, object> e = new ExpandoObject();
      
          for (var i = 0; i < dr.FieldCount; i++)
              e.Add(dr.GetName(i), DBNull.Value.Equals(dr[i]) ? null : dr[i]);
      
          result.Add(e);
      }
      

      从调用方法你“作弊”。你知道你的动态集合是ExpandoObject,所以

      foreach (IDictionary<string, object> row in result)
      {
          foreach (var kv in row)
          {
              Console.WriteLine("{0}: {1}", kv.Key, kv.Value);
          }
      }
      

      最后,最好你的方法只返回一个List&lt;IDictionary&lt;string, object&gt;&gt;,而不需要dynamic

      对动态类型的反思很难。除非你可以使用鸭子打字(鸭子打字是当你知道对象可以Duck(),即使你不知道它到底是什么,所以你可以做dynamic x = something; x.Duck();),那么它只是半困难的。如果您对此不信任,可以尝试阅读How do I reflect over the members of dynamic object?

      【讨论】:

        猜你喜欢
        • 2020-09-11
        • 2016-07-01
        • 2020-03-01
        • 2011-01-18
        • 2014-09-06
        • 2017-02-23
        • 1970-01-01
        • 2020-11-13
        • 1970-01-01
        相关资源
        最近更新 更多