This question already has an answer here:
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.
ExpandoObject
is what is special here, nothing else. It's not actually mutating the definition of the type itself at runtime. What's actually going on here is that the apparent property accesses are actually mutating anIDictionary<string,object>
that is held behind the scenes. To access the properties of anExpandoObject
(note this won't work for any other type) you can cast it toIDictionary<string,object>
, which is the intended mechanism of getting that data from anExpandoObject
.In order to get the values via reflection for a dynamically-constructed type, you'll need to use
Reflection.Emit
. This is less than ideal as it requires you to properly emit MSIL. If your use case requires only simple property access, then it may be feasible, though ill-advised.Here's a simple, lightly-tested, type builder that uses
Reflection.Emit
:You would create the type, then populate it as such:
Your first example is an anonymous object. The compiler actually generates a type behind the scenes that you can reflect on.
The second example uses an
ExpandoObject
to back your dynamic object.ExpandoObject
has no properties of its own which is why your call returns what it does.ExpandoObject
does explicitly implementIDictionary<string, object>
that gives you access to the properties and their values. You can use it as follows:You don't need reflection with
ExpandoObject
. It's really just a fancy implementation ofIDictionary<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:Another option would be to use the features of an
IDynamicMetaObjectProvider
, whichExpandoObject
also implements. Usage would look like:In this case
propertyNames
would be anIEnumerable<string>
with the dynamic member names.