c# foreach (property in object)... Is there a simple way of doing this?

C#PropertiesForeachGeneric List

C# Problem Overview


I have a class containing several properties (all are strings if it makes any difference).
I also have a list, which contains many different instances of the class.

While creating some unit tests for my classes I decided I wanted to loop through each object in the list and then loop through each property of that object...

I thought doing this would be as simple as...

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

But this didnt work! :( I get this error...

"foreach statement cannot operate on variables of type 'Application.Object' because 'Application.Object' does not contain a public definition for 'GetEnumerator'"

Does anyone know of a way of doing this without tons of ifs and loops or without getting into anything too complex?

C# Solutions


Solution 1 - C#

Give this a try:

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

Also please note that Type.GetProperties() has an overload which accepts a set of binding flags so you can filter out properties on a different criteria like accessibility level, see MSDN for more details: Type.GetProperties Method (BindingFlags) Last but not least don't forget to add the "system.Reflection" assembly reference.

For instance to resolve all public properties:

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

Please let me know whether this works as expected.

Solution 2 - C#

You can loop through all non-indexed properties of an object like this:

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

Since GetProperties() returns indexers as well as simple properties, you need an additional filter before calling GetValue to know that it is safe to pass null as the second parameter.

You may need to modify the filter further in order to weed out write-only and otherwise inaccessible properties.

Solution 3 - C#

Your'e almost there, you just need to get the properties from the type, rather than expect the properties to be accessible in the form of a collection or property bag:

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

From there you can access like so:

property.Name
property.GetValue(obj, null)

With GetValue the second parameter will allow you to specify index values, which will work with properties returning collections - since a string is a collection of chars, you can also specify an index to return a character if needs be.

Solution 4 - C#

Sure, no problem:

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

Solution 5 - C#

Use Reflection to do this

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

Solution 6 - C#

I looked for the answer to a similar question on this page, I wrote the answers to several similar questions that may help people who enter this page.

Class List

List < T > class represents the list of objects which can be accessed by index. It comes under the System.Collection.Generic namespace. List class can be used to create a collection of different types like integers, strings etc. List class also provides the methods to search, sort, and manipulate lists.

Class with property:

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 with field:

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, List of objects (without same cells):

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, List of objects (It must have the same cells):

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, List of objects (with key):

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, List of Dictionary

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

Good luck..

Solution 7 - C#

A small word of caution, if "do some stuff" means updating the value of the actual property that you visit AND if there is a struct type property along the path from root object to the visited property, the change you made on the property will not be reflected on the root object.

Solution 8 - C#

A copy-paste solution (extension methods) mostly based on earlier responses to this question.

Also properly handles IDicitonary (ExpandoObject/dynamic) which is often needed when dealing with this reflected stuff.

Not recommended for use in tight loops and other hot paths. In those cases you're gonna need some caching/IL emit/expression tree compilation.

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

Solution 9 - C#

For me the solution was to change GetProperties() to GetRuntimeProperties().

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

Solution 10 - C#

I couldn't get any of the above ways to work, but this worked. The username and password for DirectoryEntry are optional.

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJammerz858View Question on Stackoverflow
Solution 1 - C#sllView Answer on Stackoverflow
Solution 2 - C#Sergey KalinichenkoView Answer on Stackoverflow
Solution 3 - C#Grant ThomasView Answer on Stackoverflow
Solution 4 - C#Eric LippertView Answer on Stackoverflow
Solution 5 - C#ArionView Answer on Stackoverflow
Solution 6 - C#Sajad MirzaeiView Answer on Stackoverflow
Solution 7 - C#Dogu ArslanView Answer on Stackoverflow
Solution 8 - C#Zar ShardanView Answer on Stackoverflow
Solution 9 - C#Iván KollárView Answer on Stackoverflow
Solution 10 - C#BbbView Answer on Stackoverflow