3

I have some sample code looking like this:

var items = new List<object>();

var testObjectOne = new
{
    Valueone = "test1",
    ValueTwo = "test2",
    ValueThree = "test3"
};
var testObjectTwo = new
{
    Valueone = "test1",
    ValueTwo = "test2",
    ValueThree = "test3"
};
items.Add(testObjectOne);
items.Add(testObjectTwo);

foreach (var obj in items)
{
    var val = obj.Valueone;
}

But I can't access Valueone and get the error: object' does not contain a definition for 'Valueone' and no extension method 'Valueone' accepting a first argument of type 'object' could be found (are you missing a using directive or an assembly reference?)

Question: How can i iterate through this list and access ValueOne for example? Any help or input is highly appreciated, thanks

Souvik Ghosh
  • 4,234
  • 12
  • 51
  • 72
Mattias
  • 2,617
  • 5
  • 26
  • 45
  • 1
    `var items = (new[] { testObjectOne }).ToList()`. Or `new List()`. Or a helper method to infer the list type without actually adding objects. Or use tuples. Or, my personal favorite option, don't be lazy and just declare a class. – Jeroen Mostert Aug 11 '17 at 08:31
  • This sounds like a xy-problem. Why don't you create a dedicated type for your testobjects and put the instances in a `List`? – René Vogt Aug 11 '17 at 08:31
  • 1
    The items in your list are of type `object` who doesn't hold a definition for `ValueOne`. You could do something like `var items = Enumerable.Empty().Select(o=>{/*Anonymous definition*/}).ToList()`. – dcg Aug 11 '17 at 08:31

6 Answers6

7

You could use reflection to fetch properties of anonymous types:

var items = new List<object>();

var testObjectOne = new
{
    Valueone = "test1",
    ValueTwo = "test2",
    ValueThree = "test3"
    };
var testObjectTwo = new
{
    Valueone = "test1",
    ValueTwo = "test2",
    ValueThree = "test3"
};
items.Add(testObjectOne);
items.Add(testObjectTwo);

foreach (var obj in items)
{
    var val = obj.GetType()
        .GetProperty("Valueone")
        .GetValue(obj);
}
senz
  • 799
  • 6
  • 24
4

Another solution without reflection would be to create a list of anonymous objects like:

var items = Enumerable.Empty<object>().Select(o=>{
                Valueone = "test1",
                ValueTwo = "test2",
                ValueThree = "test3"
            }).ToList();

Edit: Adding an object to the list

items.Add(new {
    Valueone = "Value one",
    ValueTwo = "Value two",
    ValueThree = "Value three"
});

then inside the for the statement var val = obj.Valueone will compile successfully.

dcg
  • 4,020
  • 1
  • 17
  • 30
  • This will just create an empty list of an anonymous type, no way to iterate it. – MakePeaceGreatAgain Aug 25 '17 at 08:23
  • @HimBromBeere In deed. I only pointed out a way to create the list of anonymous objects.I edited my answer to show how to add an item to the list. Thanks. – dcg Sep 01 '17 at 12:10
3

You have to use reflection if you will not cast it back to its original object

System.Reflection.PropertyInfo pi = item.GetType().GetProperty("Valueone");
string Valueone = (string)(pi.GetValue(item, null));

Or you can change the object to dynamic

var items = new List<dynamic>();

var testObjectOne = new
{
    Valueone = "test1",
    ValueTwo = "test2",
    ValueThree = "test3"
};
items.Add(testObjectOne);
items.Add(testObjectTwo);

foreach (var obj in items)
{
    var val = obj.Valueone;
}
Jakub Dąbek
  • 1,014
  • 1
  • 8
  • 16
npo
  • 1,050
  • 8
  • 9
3

why not create a class to represent these objects?=! It would make your code more solid and you can avoid slow/costly reflection or unsafe /bad practice dynamic acrobatics:

public class TempObject
{
    public string Valueone { get; set; }
    public string ValueTwo { get; set; }
    public string ValueThree { get; set; }
}

var items = new List<TempObject>();

var testObjectOne = new TempObject
{
    Valueone = "test1",
    ValueTwo = "test2",
    ValueThree = "test3"
};

items.Add(testObjectOne);

foreach (var obj in items)
{
    var val = obj.Valueone;
}
Mong Zhu
  • 21,868
  • 8
  • 38
  • 71
3

Simply create your list as of anonymous type also, not as `List:

var list = new[] { new
        {
            Valueone = "test1",
            ValueTwo = "test2",
            ValueThree = "test3"
        },
        new
        {
            Valueone = "test1",
            ValueTwo = "test2",
            ValueThree = "test3"
        }
    }.ToList();

You can even add new elements to the list:

list.Add(new {
    Valueone = "test1",
    ValueTwo = "test2",
    ValueThree = "test3"
});

Now you can easily iterate that array using var:

foreach(var e in list) ...

No need for reflection at all, everything is strongly-typed.

MakePeaceGreatAgain
  • 33,293
  • 6
  • 51
  • 100
1
        //Anonymous object in C#
        var any = new { UserName = "Adel@gmail.com", Password = "P@ssw0rd" };

        //Array of anonymous objects in C#
        object[] defaultUsers = {
            new {UserName = "Adel@gmail.com", Password = "P@ssw0rd" },
            new {UserName = "Mike@gmail.com", Password = "P@ssw0rd" },
            new {UserName = "John@gmail.com", Password = "P@ssw0rd" }
        };

        //Iterate through a list of anonymous objects in C#
        foreach (var user in defaultUsers)
        {
            var userName = user.GetType().GetProperty("UserName").GetValue(user);
            var password = user.GetType().GetProperty("Password").GetValue(user);
        }

So that you better make a model for the data

    public class DefaultUser
{
    public string UserName { get; set; }
    public string Password { get; set; }
    public string Role { get; set; }
}

Then do it this way, that's cleaner

        DefaultUser[] defaultUsers = {
            new DefaultUser() { UserName = "admin@user.com", Password = "P@ssword10", Role = "Admins"},
            new DefaultUser() { UserName = "author@user.com", Password = "P@ssword10", Role="Authors"},
            new DefaultUser() { UserName = "reader@user.com", Password = "P@ssword10", Role="Readers"}};

        foreach (DefaultUser user in defaultUsers)
        {
            var userName = user.UserName;
            var password = user.Password;
        }
Adel Mourad
  • 1,123
  • 13
  • 10