能否在List<dynamic>上进行迭代?

4
在过去的几天里,我一直试图找到一种迭代 List<dynamic> 的方法,但没有太大的成功。
这是我的做法:
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<dynamic> 的方法。在我的控制器中,我使用以下代码获取数据:

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

现在我陷入了困境,因为我需要迭代irionErrorsExport并创建一个"具体"的对象/来与EPPlus一起使用。

有人能告诉我这是否可能,并给出一个简单的示例吗?


GetStrCtrlDGWithErrors() 是您的方法,其中包含第一段代码吗? - siride
1
展示一下 GetStrCtrlDGWithErrors 方法的签名。 - MarcinJuraszek
请注意,您可以执行以下操作:IDictionary<string, object> e = new ExpandoObject(),将 d.* 更改为 e.* ,然后在不进行中间转换的情况下执行 result.Add(e) - xanatos
3个回答

2

是的,您可以迭代 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”

编辑:您需要了解在普通变量和dynamic上使用foreach的差异。它们在另一个 SO 问题中有详细解释:C# 4.0 'dynamic' and foreach statement

1
如果您像这里一样填充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; }
}

0
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<IDictionary<string, object>>,那就更好了,不需要使用dynamic
动态类型的反射很困难。除非你可以使用鸭子类型(鸭子类型是指当你知道对象可以Duck()时,即使你不知道它到底是什么,你也可以这样做:dynamic x = something; x.Duck();),否则它只是半困难。如果你不相信我,可以试着阅读如何反射动态对象的成员?

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接