c#foreach(对象中的属性)…是否有一种简单的方法?


92

我有一个包含多个属性的类(如果有区别,则全部为字符串)。
我还有一个列表,其中包含该类的许多不同实例。

在为类创建一些单元测试时,我决定要遍历列表中的每个对象,然后遍历该对象的每个属性...

我以为这样做很简单...

foreach (Object obj in theList)
{
     foreach (Property theProperties in obj)
     {
         do some stufff!!;
     }
}

但是,这没有用!:(我收到此错误...

“ foreach语句无法对'Application.Object'类型的变量进行操作,因为'Application.Object'不包含'GetEnumerator'的公共定义”

有谁知道这样做的方法而没有大量的if和loop或没有陷入任何过于复杂的情况?


5
将来,请不要在一个问题中说“它不起作用”。相反,请指定您遇到的问题(编译器错误等)。谢谢!
罗伯特·哈维

2
更新!Robert
Jammerz858

Answers:


143

试试看:

foreach (PropertyInfo propertyInfo in obj.GetType().GetProperties())
{
   // do stuff here
}

还请注意,它Type.GetProperties()具有一个接受一组绑定标志的重载,因此您可以根据其他条件(如可访问性级别)过滤掉属性,有关更多详细信息,请参见MSDN:Type.GetProperties方法(BindingFlags)最后但并非最不重要的一点是,不要忘记添加“ system.Reflection”程序集引用。

例如解决所有公共财产:

foreach (var propertyInfo in obj.GetType()
                                .GetProperties(
                                        BindingFlags.Public 
                                        | BindingFlags.Instance))
{
   // do stuff here
}

请让我知道这是否按预期工作。


4
一旦掌握了对象的属性,无论如何,都可以获取每个属性的值吗?例如,名称或邮政编码
JsonStatham

35

您可以像这样遍历对象的所有非索引属性:

var s = new MyObject();
foreach (var p in s.GetType().GetProperties().Where(p => !p.GetGetMethod().GetParameters().Any())) {
    Console.WriteLine(p.GetValue(s, null));
}

由于GetProperties()返回索引器和简单属性,因此在调用之前需要一个附加过滤器,GetValue以知道可以安全地null作为第二个参数传递。

您可能需要进一步修改过滤器,以清除只写属性和其他无法访问的属性。


+1表示仅对可以实际使用的属性进行处理-您可能还希望过滤掉只写属性。

@hvd这是只写属性的一个好地方!我几乎忘记了他们。如果我的代码遇到带有nullgetter 的属性,则将崩溃,但是我确信OP将弄清楚如何仅获取他需要的属性。
dasblinkenlight 2012年

27

差不多了,您只需要从类型中获取属性,而不是希望可以通过集合或属性包的形式访问这些属性:

var property in obj.GetType().GetProperties()

从那里您可以像这样访问

property.Name
property.GetValue(obj, null)

使用GetValue第二个参数将允许您指定索引值,该值将与返回集合的属性一起使用-由于字符串是chars的集合,因此您还可以指定索引以在需要时返回字符。


1
我难过了吗?我愿意知道这是怎么回事,否则我可能永远也不会学习。
格兰·托马斯

当您的代码错误时(在您的忍者编辑之前),您可能会感到失望。
罗伯特·哈维

20

好没问题:

foreach(object item in sequence)
{
    if (item == null) continue;
    foreach(PropertyInfo property in item.GetType().GetProperties())
    {
        // do something with the property
    }
}

为什么要添加此行?if (item == null) continue;我个人认为,如果那时您有一个空对象,那早就出了点问题,那就是验证应该在的地方,还是我错了?
拉斐尔·赫斯科维奇

@Dementic:当然,我们可以说该序列必须包含非空引用。
埃里克·利珀特

3

使用反射来做到这一点

SomeClass A = SomeClass(...)
PropertyInfo[] properties = A.GetType().GetProperties();

1

我在此页面上寻找类似问题的答案,并写了一些类似问题的答案,这些问题可能会对进入此页面的人有所帮助。

班级清单

List <T>类表示可以通过索引访问的对象列表。它位于System.Collection.Generic命名空间下。列表类可用于创建不同类型的集合,例如整数,字符串等。列表类还提供了搜索,排序和操作列表的方法。

具有属性的类

class TestClss
{
    public string id { set; get; }
    public string cell1 { set; get; }
    public string cell2 { set; get; }
}
var MyArray = new List<TestClss> {
    new TestClss() { id = "1", cell1 = "cell 1 row 1 Data", cell2 = "cell 2 row 1 Data" },
    new TestClss() { id = "2", cell1 = "cell 1 row 2 Data", cell2 = "cell 2 row 2 Data" },
    new TestClss() { id = "3", cell1 = "cell 1 row 2 Data", cell2 = "cell 2 row 3 Data" }
};
foreach (object Item in MyArray)
{
    Console.WriteLine("Row Start");
    foreach (PropertyInfo property in Item.GetType().GetProperties())
    {
        var Key = property.Name;
        var Value = property.GetValue(Item, null);
        Console.WriteLine("{0}={1}", Key, Value);
    }
}

或,带有字段的类

class TestClss
{
    public string id = "";
    public string cell1 = "";
    public string cell2 = "";
}
var MyArray = new List<TestClss> {
    new TestClss() { id = "1", cell1 = "cell 1 row 1 Data", cell2 = "cell 2 row 1 Data" },
    new TestClss() { id = "2", cell1 = "cell 1 row 2 Data", cell2 = "cell 2 row 2 Data" },
    new TestClss() { id = "3", cell1 = "cell 1 row 2 Data", cell2 = "cell 2 row 3 Data" }
};
foreach (object Item in MyArray)
{
    Console.WriteLine("Row Start");
    foreach (var fieldInfo in Item.GetType().GetFields())
    {
        var Key = fieldInfo.Name;
        var Value = fieldInfo.GetValue(Item);
    }

}

或,对象列表(没有相同的单元格):

var MyArray = new List<object> {
    new { id = "1", cell1 = "cell 1 row 1 Data", cell2 = "cell 2 row 1 Data" },
    new { id = "2", cell1 = "cell 1 row 2 Data", cell2 = "cell 2 row 2 Data" },
    new { id = "3", cell1 = "cell 1 row 2 Data", cell2 = "cell 2 row 3 Data", anotherCell = "" }
};
foreach (object Item in MyArray)
{
    Console.WriteLine("Row Start");
    foreach (var props in Item.GetType().GetProperties())
    {
        var Key = props.Name;
        var Value = props.GetMethod.Invoke(Item, null).ToString();
        Console.WriteLine("{0}={1}", Key, Value);
    }
}

或,对象列表(必须具有相同的单元格):

var MyArray = new[] {
    new { id = "1", cell1 = "cell 1 row 1 Data", cell2 = "cell 2 row 1 Data" },
    new { id = "2", cell1 = "cell 1 row 2 Data", cell2 = "cell 2 row 2 Data" },
    new { id = "3", cell1 = "cell 1 row 2 Data", cell2 = "cell 2 row 3 Data" }
};
foreach (object Item in MyArray)
{
    Console.WriteLine("Row Start");
    foreach (var props in Item.GetType().GetProperties())
    {
        var Key = props.Name;
        var Value = props.GetMethod.Invoke(Item, null).ToString();
        Console.WriteLine("{0}={1}", Key, Value);
    }
}

或,对象列表(带键):

var MyArray = new {
    row1 = new { id = "1", cell1 = "cell 1 row 1 Data", cell2 = "cell 2 row 1 Data" },
    row2 = new { id = "2", cell1 = "cell 1 row 2 Data", cell2 = "cell 2 row 2 Data" },
    row3 = new { id = "3", cell1 = "cell 1 row 2 Data", cell2 = "cell 2 row 3 Data" }
};
// using System.ComponentModel;  for TypeDescriptor
foreach (PropertyDescriptor Item in TypeDescriptor.GetProperties(MyArray))
{
    string Rowkey = Item.Name;
    object RowValue = Item.GetValue(MyArray);
    Console.WriteLine("Row key is: {0}", Rowkey);
    foreach (var props in RowValue.GetType().GetProperties())
    {
        var Key = props.Name;
        var Value = props.GetMethod.Invoke(RowValue, null).ToString();
        Console.WriteLine("{0}={1}", Key, Value);
    }
}

或,词典列表

var MyArray = new List<Dictionary<string, string>>() {
    new Dictionary<string, string>() { { "id", "1" }, { "cell1", "cell 1 row 1 Data" }, { "cell2", "cell 2 row 1 Data" } },
    new Dictionary<string, string>() { { "id", "2" }, { "cell1", "cell 1 row 2 Data" }, { "cell2", "cell 2 row 2 Data" } },
    new Dictionary<string, string>() { { "id", "3" }, { "cell1", "cell 1 row 3 Data" }, { "cell2", "cell 2 row 3 Data" } }
};
foreach (Dictionary<string, string> Item in MyArray)
{
    Console.WriteLine("Row Start");
    foreach (KeyValuePair<string, string> props in Item)
    {
        var Key = props.Key;
        var Value = props.Value;
        Console.WriteLine("{0}={1}", Key, Value);
    }
}

祝好运..


0

请注意,如果“做一些事情”意味着更新您访问的实际属性的值,并且如果从根对象到被访问的属性的路径上存在结构类型的属性,则您对该属性所做的更改将不能反映在根对象上。


0

我无法获得上述任何一种工作方式,但这确实可行。DirectoryEntry的用户名和密码是可选的。

   private List<string> getAnyDirectoryEntryPropertyValue(string userPrincipalName, string propertyToSearchFor)
    {
        List<string> returnValue = new List<string>();
        try
        {
            int index = userPrincipalName.IndexOf("@");
            string originatingServer = userPrincipalName.Remove(0, index + 1);
            string path = "LDAP://" + originatingServer; //+ @"/" + distinguishedName;
            DirectoryEntry objRootDSE = new DirectoryEntry(path, PSUsername, PSPassword);
            var objSearcher = new System.DirectoryServices.DirectorySearcher(objRootDSE);
            objSearcher.Filter = string.Format("(&(UserPrincipalName={0}))", userPrincipalName);
            SearchResultCollection properties = objSearcher.FindAll();

            ResultPropertyValueCollection resPropertyCollection = properties[0].Properties[propertyToSearchFor];
            foreach (string resProperty in resPropertyCollection)
            {
                returnValue.Add(resProperty);
            }
        }
        catch (Exception ex)
        {
            returnValue.Add(ex.Message);
            throw;
        }

        return returnValue;
    }

0

复制粘贴解决方案(扩展方法)主要基于对该问题的较早答复。

还可以正确处理IDentitonary(ExpandoObject / dynamic),这在处理这些反映的内容时经常需要。

不建议在紧密循环和其他热路径中使用。在这些情况下,您将需要一些缓存/ IL发射/表达式树编译。

    public static IEnumerable<(string Name, object Value)> GetProperties(this object src)
    {
        if (src is IDictionary<string, object> dictionary)
        {
            return dictionary.Select(x => (x.Key, x.Value));
        }
        return src.GetObjectProperties().Select(x => (x.Name, x.GetValue(src)));
    }

    public static IEnumerable<PropertyInfo> GetObjectProperties(this object src)
    {
        return src.GetType()
            .GetProperties(BindingFlags.Public | BindingFlags.Instance)
            .Where(p => !p.GetGetMethod().GetParameters().Any());
    }
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.