Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make .NET reflection to work with dynamically generated objects? [duplicate]

Look at the following example:

void Main()
{
    // APPROACH 1: With an anonymous type
    var myObject = new {
        Property1 = "PropertyValue1"
    };

    // WORKS: Properties contains "Property1"
    var properties = myObject.GetType().GetProperties();

    // APPROACH 2: With an expando object
    dynamic myObject2 = new ExpandoObject();
    myObject2.Property1 = "PropertyValue1";

    // DOES NOT WORK: Properties2 is null or empty
    var properties2 = myObject2.GetType().GetProperties();
}

What I want is to make Type.GetProperties() to work on a dynamically generated type. I really understand why it works in the approach 1 and not 2. Actually, in the approach 1, the compiler has the oportunity to generate an anonymous type that looks exactly like a named type. In the approach 2, however, the compile time type is actually an ExpandoObject, so reflection doesn't work properly.

How do I create a runtime object, that is dynamic and will also work normally with reflection, like the GetProperties method?

EDIT

Thanks for all answers, but I really understand and I know how to get the keys and values from the ExpandoObject.. The problem is that I need to pass a dynamically created instance to a method, outside my control that will, in turn, call GetProperties() on the instance.

like image 909
André Pena Avatar asked Jun 02 '14 20:06

André Pena


1 Answers

You don't need reflection with ExpandoObject. It's really just a fancy implementation of IDictionary<string, object>. You can cast it as such, and then you will have a dictionary where the keys are the property names and the values are the property values:

// Create your object
dynamic myObject2 = new ExpandoObject();

// Cast to IDictionary<string, object>
var myObjectDictionary = (IDictionary<string, object>)myObject2;

// Get List<string> of properties
var propertyNames = myObjectDictionary.Keys.ToList();

Another option would be to use the features of an IDynamicMetaObjectProvider, which ExpandoObject also implements. Usage would look like:

var metaObjectProvider = (IDynamicMetaObjectProvider)myObject2;
var propertyNames = metaObjectProvider
    .GetMetaObject(Expression.Constant(metaObjectProvider))
    .GetDynamicMem‌​berNames();

In this case propertyNames would be an IEnumerable<string> with the dynamic member names.

like image 85
Cᴏʀʏ Avatar answered Sep 22 '22 00:09

Cᴏʀʏ