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

.net, c#, reflection

Solution

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`:

    public static class TypeBuilderUtil {
        public static Type BuildDynamicType() {
            var typeBuilder = CreateTypeBuilder( "DynamicType" );
            CreateProperty( typeBuilder, "Property1", typeof ( string ) );

            var objectType = typeBuilder.CreateType();
            return objectType;
        }

        private static TypeBuilder CreateTypeBuilder( string typeName ) {
            var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly( new AssemblyName( "DynamicAssembly" ), AssemblyBuilderAccess.Run );
            var moduleBuilder = assemblyBuilder.DefineDynamicModule( "DynamicModule" );
            var typeBuilder = moduleBuilder.DefineType( typeName,
                                                        TypeAttributes.Public | TypeAttributes.Class | TypeAttributes.AutoClass | TypeAttributes.AnsiClass | TypeAttributes.BeforeFieldInit | TypeAttributes.AutoLayout
                                                        , null );
            return typeBuilder;
        }

        private static void CreateProperty( TypeBuilder typeBuilder, string propertyName, Type propertyType ) {
            var backingFieldBuilder = typeBuilder.DefineField( "_" + propertyName, propertyType, FieldAttributes.Private );
            var propertyBuilder = typeBuilder.DefineProperty( propertyName, PropertyAttributes.HasDefault, propertyType, null );
            // Build setter
            var getterMethodBuilder = typeBuilder.DefineMethod( "get_" + propertyName, MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig, propertyType, Type.EmptyTypes );
            var getterIl = getterMethodBuilder.GetILGenerator();
            getterIl.Emit( OpCodes.Ldarg_0 );
            getterIl.Emit( OpCodes.Ldfld, backingFieldBuilder );
            getterIl.Emit( OpCodes.Ret );

            // Build setter
            var setterMethodBuilder = typeBuilder.DefineMethod( "set_" + propertyName, MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig, null, new[] {propertyType} );
            var setterIl = setterMethodBuilder.GetILGenerator();
            setterIl.Emit( OpCodes.Ldarg_0 );
            setterIl.Emit( OpCodes.Ldarg_1 );
            setterIl.Emit( OpCodes.Stfld, backingFieldBuilder );
            setterIl.Emit( OpCodes.Ret );

            propertyBuilder.SetGetMethod( getterMethodBuilder );
            propertyBuilder.SetSetMethod( setterMethodBuilder );
        }
    }

You would create the type, then populate it as such:

        var myType = TypeBuilderUtil.BuildDynamicType();
        var myObject = Activator.CreateInstance( myType );

        // Set the value
        var propertyInfo = myObject.GetType().GetProperty( "Property1", BindingFlags.Instance | BindingFlags.Public );
        propertyInfo.SetValue( myObject, "PropertyValue", null );

Problem

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.

Original source

Related problems