How do I iterate over the properties of an anonymous object in C#?

C#PropertiesIterationAnonymous Types

C# Problem Overview


I want to take an anonymous object as argument to a method, and then iterate over its properties to add each property/value to a a dynamic ExpandoObject.

So what I need is to go from

new { Prop1 = "first value", Prop2 = SomeObjectInstance, Prop3 = 1234 }

to knowing names and values of each property, and being able to add them to the ExpandoObject.

How do I accomplish this?

Side note: This will be done in many of my unit tests (I'm using it to refactor away a lot of junk in the setup), so performance is to some extent relevant. I don't know enough about reflection to say for sure, but from what I've understood it's pretty performance heavy, so if it's possible I'd rather avoid it...

Follow-up question: As I said, I'm taking this anonymous object as an argument to a method. What datatype should I use in the method's signature? Will all properties be available if I use object?

C# Solutions


Solution 1 - C#

foreach(var prop in myVar.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public))
{
   Console.WriteLine("Name: {0}, Value: {1}",prop.Name, prop.GetValue(myVar,null));
}

Solution 2 - C#

Reflect on the anonymous object to get its property names and values, then take advantage of an ExpandoObject actually being a dictionary to populate it. Here's an example, expressed as a unit test:

	[TestMethod]
	public void ShouldBeAbleToConvertAnAnonymousObjectToAnExpandoObject()
	{
		var additionalViewData = new {id = "myControlId", css = "hide well"};
		dynamic result = new ExpandoObject();
		var dict = (IDictionary<string, object>)result;
		foreach (PropertyInfo propertyInfo in additionalViewData.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public))
		{
			dict[propertyInfo.Name] = propertyInfo.GetValue(additionalViewData, null);
		}
		Assert.AreEqual(result.id, "myControlId");
		Assert.AreEqual(result.css, "hide well");
	}

Solution 3 - C#

An alternative approach is to use DynamicObject instead of ExpandoObject, and that way you only have the overhead of doing the reflection if you actually try to access a property from the other object.

public class DynamicForwarder : DynamicObject 
{
    private object _target;

    public DynamicForwarder(object target)
    {
        _target = target;
    }

    public override bool TryGetMember(
        GetMemberBinder binder, out object result)
    {
        var prop = _target.GetType().GetProperty(binder.Name);
        if (prop == null)
        {
            result = null;
            return false;
        }

        result = prop.GetValue(_target, null);
        return true;
    }
}

Now it only does the reflection when you actually try to access the property via a dynamic get. On the downside, if you repeatedly access the same property, it has to do the reflection each time. So you could cache the result:

public class DynamicForwarder : DynamicObject 
{
    private object _target;
    private Dictionary<string, object> _cache = new Dictionary<string, object>();

    public DynamicForwarder(object target)
    {
        _target = target;
    }

    public override bool TryGetMember(
        GetMemberBinder binder, out object result)
    {
        // check the cache first
        if (_cache.TryGetValue(binder.Name, out result))
            return true;

        var prop = _target.GetType().GetProperty(binder.Name);
        if (prop == null)
        {
            result = null;
            return false;
        }

        result = prop.GetValue(_target, null);
        _cache.Add(binder.Name, result); // <-------- insert into cache
        return true;
    }
}

You could support storing a list of target objects to coalesce their properties, and support setting properties (with a similar override called TrySetMember) to allow you to dynamically set values in the cache dictionary.

Of course, the overhead of reflection is probably not going to be worth worrying about, but for large objects this could limit the impact of it. What is maybe more interesting is the extra flexibility it gives you.

Solution 4 - C#

This is an old question, but now you should be able to do this with the following code:

dynamic expObj = new ExpandoObject();
    expObj.Name = "James Kirk";
    expObj.Number = 34;

// print the dynamically added properties
// enumerating over it exposes the Properties and Values as a KeyValuePair
foreach (KeyValuePair<string, object> kvp in expObj){ 
    Console.WriteLine("{0} = {1} : Type: {2}", kvp.Key, kvp.Value, kvp.Value.GetType());
}

The output would look like the following:

> Name = James Kirk : Type: System.String > > Number = 34 : Type: > System.Int32

Solution 5 - C#

you have to use reflection.... (code "borrowed" from this url)

using System.Reflection;  // reflection namespace

// get all public static properties of MyClass type
PropertyInfo[] propertyInfos;
propertyInfos = typeof(MyClass).GetProperties(BindingFlags.Public |
                                              BindingFlags.Static);
// sort properties by name
Array.Sort(propertyInfos,
        delegate(PropertyInfo propertyInfo1, PropertyInfo propertyInfo2)
        { return propertyInfo1.Name.CompareTo(propertyInfo2.Name); });

// write property names
foreach (PropertyInfo propertyInfo in propertyInfos)
{
  Console.WriteLine(propertyInfo.Name);
}

Solution 6 - C#

Use Reflection.Emit to create a generic method to fill an ExpandoObject.

OR use Expressions perhaps (I think this would only be possible in .NET 4 though).

Neither of these approaches uses reflection when invoking, only during setup of a delegate (which obviously needs to be cached).

Here is some Reflection.Emit code to fill a dictionary (I guess ExpandoObject is not far off);

static T CreateDelegate<T>(this DynamicMethod dm) where T : class
{
  return dm.CreateDelegate(typeof(T)) as T;
}

static Dictionary<Type, Func<object, Dictionary<string, object>>> cache = 
   new Dictionary<Type, Func<object, Dictionary<string, object>>>();

static Dictionary<string, object> GetProperties(object o)
{
  var t = o.GetType();

  Func<object, Dictionary<string, object>> getter;

  if (!cache.TryGetValue(t, out getter))
  {
    var rettype = typeof(Dictionary<string, object>);

    var dm = new DynamicMethod(t.Name + ":GetProperties", rettype, 
       new Type[] { typeof(object) }, t);

    var ilgen = dm.GetILGenerator();

    var instance = ilgen.DeclareLocal(t);
    var dict = ilgen.DeclareLocal(rettype);

    ilgen.Emit(OpCodes.Ldarg_0);
    ilgen.Emit(OpCodes.Castclass, t);
    ilgen.Emit(OpCodes.Stloc, instance);

    ilgen.Emit(OpCodes.Newobj, rettype.GetConstructor(Type.EmptyTypes));
    ilgen.Emit(OpCodes.Stloc, dict);

    var add = rettype.GetMethod("Add");

    foreach (var prop in t.GetProperties(
      BindingFlags.Instance |
      BindingFlags.Public))
    {
      ilgen.Emit(OpCodes.Ldloc, dict);
      
      ilgen.Emit(OpCodes.Ldstr, prop.Name);
      
      ilgen.Emit(OpCodes.Ldloc, instance);
      ilgen.Emit(OpCodes.Ldfld, prop);
      ilgen.Emit(OpCodes.Castclass, typeof(object));

      ilgen.Emit(OpCodes.Callvirt, add);
    }

    ilgen.Emit(OpCodes.Ldloc, dict);
    ilgen.Emit(OpCodes.Ret);

    cache[t] = getter = 
      dm.CreateDelegate<Func<object, Dictionary<string, object>>>();
  }

  return getter(o);
}

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
QuestionTomas AschanView Question on Stackoverflow
Solution 1 - C#BFreeView Answer on Stackoverflow
Solution 2 - C#Jonathan MoffattView Answer on Stackoverflow
Solution 3 - C#Daniel EarwickerView Answer on Stackoverflow
Solution 4 - C#raddevusView Answer on Stackoverflow
Solution 5 - C#Muad'DibView Answer on Stackoverflow
Solution 6 - C#leppieView Answer on Stackoverflow