stondo
stondo

Reputation: 131

Is it possible to iterate on List<dynamic>?

In the past few days I've been trying to find a way to iterate on a List<dynamic> without much success.

That's what I'm doing:

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);
}

the above code is a method that returns an IEnumerable<dynamic> then in my controller I'm getting data back with:

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

and now I'm stuck since I need to iterate on irionErrorsExport and create a "concrete" object/s to use with EPPlus.

Can anyone please tell me if it is even possible and show a simple example?

Upvotes: 4

Views: 4986

Answers (3)

xanatos
xanatos

Reputation: 111920

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);
}

From the calling method you "cheat". You know that your dynamic collection is an ExpandoObject, so

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

In the end, it's better if your method simply returns a List<IDictionary<string, object>>, no dynamic necessary.

Reflection on dynamic types is hard. Unless you can use duck typing (duck typing is when you know that the object can Duck(), even if you don't know what exactly it's, so you can do dynamic x = something; x.Duck(); ), then it's only semi-hard. If you don't trust me on this, you can try reading How do I reflect over the members of dynamic object?

Upvotes: 0

MarcinJuraszek
MarcinJuraszek

Reputation: 125650

Yes, you can iterate over dynamic object:

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

Prints 123456 into console.

However, it will cause runtime exception if iteration is not possible:

Consider following code:

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

RuntimeBinderException is being thrown:

Cannot implicitly convert type 'int' to 'System.Collections.IEnumerable'

Edit: you should be aware of the differences between foreach on normal variables and dynamic. They are explained in another SO question: C# 4.0 'dynamic' and foreach statement

Upvotes: 2

I4V
I4V

Reputation: 35363

If you fill a DataTable like here, You can use Json.Net and get a concrete object easily

//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; }
}

Upvotes: 1

Related Questions