如何遍历一个匿名对象列表?

4

我有一些样例代码长这样:

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

但我无法访问Valueone并收到错误消息:对象“不包含定义为'Valueone'的内容,也没有接受类型为“object”的第一个参数的扩展方法“Valueone”(是否缺少使用指令或程序集引用?)

问题:如何遍历此列表并访问ValueOne,例如?任何帮助或输入都将不胜感激,谢谢。


1
var items = (new[] { testObjectOne }).ToList()。或者 new List<dynamic>()。或者使用一个帮助方法来推断列表类型而不实际添加对象。或者使用元组。或者,我个人最喜欢的选项是,不要懒惰,只需声明一个类。 - Jeroen Mostert
这听起来像是一个 XY 问题。为什么不为你的测试对象创建一个专用类型,并将实例放入 List<YourTestType> 中呢? - René Vogt
1
你的列表中的项是 object 类型,它没有定义 ValueOne。你可以这样做:var items = Enumerable.Empty<object>().Select(o=>{/*匿名定义*/}).ToList() - dcg
6个回答

8
您可以使用反射来获取匿名类型的属性:
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);
}

3

如果您不将其转换回原始对象,则必须使用反射。

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

或者您可以将对象更改为动态的

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

谢谢,我会改成动态的! - Mattias

3
另一种不用反射的解决方案是创建一个匿名对象列表,像这样:

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

编辑:将对象添加到列表中

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

然后在 for 内部,语句 var val = obj.Valueone 将会编译成功。


这只会创建一个匿名类型的空列表,无法迭代它。 - MakePeaceGreatAgain
@HimBromBeere 确实。我只是指出了创建匿名对象列表的方法。我编辑了我的答案,展示了如何向列表中添加项目。谢谢。 - dcg

3

为什么不创建一个类来表示这些对象呢?这会使您的代码更加稳固,避免使用缓慢/昂贵的反射不安全/糟糕的动态操作

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

3

只需将列表创建为匿名类型,而不是作为“List”:

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

你甚至可以向列表中添加新元素:
list.Add(new {
    Valueone = "test1",
    ValueTwo = "test2",
    ValueThree = "test3"
});

现在你可以很容易地使用 var 迭代该数组:
foreach(var e in list) ...

完全不需要反射,一切都是强类型的。


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

所以你最好为数据制作一个模型。
    public class DefaultUser
{
    public string UserName { get; set; }
    public string Password { get; set; }
    public string Role { get; set; }
}

那就这样做,更加简洁。
        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;
        }

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