c#foreach(对象中的属性)...有一种简单的方法吗?

时间:2012-03-27 15:48:12

标签: c# properties foreach generic-list

我有一个包含多个属性的类(如果有任何不同,则所有都是字符串) 我还有一个列表,其中包含该类的许多不同实例。

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

我认为这样做就像......一样简单。

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

但这没有用! :( 我收到这个错误......

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

有没有人知道这样做的方法没有大量的ifs和循环,或者没有进入任何过于复杂的事情?

10 个答案:

答案 0 :(得分:119)

尝试一下:

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

另请注意,Type.GetProperties()有一个重载,它接受一组绑定标记,因此您可以根据可访问性级别过滤掉不同条件的属性,有关详细信息,请参阅MSDN:Type.GetProperties Method (BindingFlags)最后但不是至少不要忘记添加“system.Reflection”程序集引用。

例如,要解决所有公共属性:

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

请告诉我这是否符合预期。

答案 1 :(得分:25)

您可以循环遍历对象的所有非索引属性,如下所示:

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作为传递是安全的第二个参数。

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

答案 2 :(得分:19)

你几乎就在那里,你只需要从类型中获取属性,而不是期望以集合或属性包的形式访问属性:

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

从那里you can access like so

property.Name
property.GetValue(obj, null)

使用GetValue,第二个参数将允许您指定索引值,这将使用返回集合的属性 - 因为字符串是字符集合,您还可以指定索引以在需要时返回字符

答案 3 :(得分:18)

当然,没问题:

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

答案 4 :(得分:3)

使用Reflection执行此操作

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

答案 5 :(得分:2)

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

Class List

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

具有属性的类

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

OR,带有字段的类

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

}

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

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

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

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

OR,对象列表(带键):

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

OR,词典列表

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

祝你好运。

答案 6 :(得分:0)

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

答案 7 :(得分: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;
    }

答案 8 :(得分:0)

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

还可以正确处理在处理这些反映的内容时经常需要使用的同质(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());
    }

答案 9 :(得分:0)

对我来说,解决方案是将 GetProperties() 更改为 GetRuntimeProperties()。

  static void EnumObject(ShareCollection obj)
    {
        foreach (PropertyInfo property in obj.GetType().GetRuntimeProperties())
        {
            property.GetValue(obj);
        }
    }