How to Reflect Over the Members of Dynamic Object

How do I reflect over the members of dynamic object?

If the IDynamicMetaObjectProvider can provide the dynamic member names, you can get them. See GetMemberNames implementation in the apache licensed PCL library Dynamitey (which can be found in nuget), it works for ExpandoObjects and DynamicObjects that implement GetDynamicMemberNames and any other IDynamicMetaObjectProvider who provides a meta object with an implementation of GetDynamicMemberNames without custom testing beyond is IDynamicMetaObjectProvider.

After getting the member names it's a little more work to get the value the right way, but Impromptu does this but it's harder to point to just the interesting bits and have it make sense. Here's the documentation and it is equal or faster than reflection, however, unlikely to be faster than a dictionary lookup for expando, but it works for any object, expando, dynamic or original - you name it.

Dynamically adding members to a dynamic object

What you want is similar to Python's getattr/setattr functions. There's no built in equivalent way to do this in C# or VB.NET. The outer layer of the DLR (which ships w/ IronPython and IronRuby in Microsoft.Scripting.dll) includes a set of hosting APIs which includes an ObjectOperations API that has GetMember/SetMember methods. You could use those but you'd need the extra dependency of the DLR and a DLR based language.

Probably the simplest approach would be to create a CallSite w/ one of the existing C# binders. You can get the code for this by looking at the result of "foo.Bar = 42" in ildasm or reflector. But a simple example of this would be:

object x = new ExpandoObject();
CallSite<Func<CallSite, object, object, object>> site = CallSite<Func<CallSite, object, object, object>>.Create(
Binder.SetMember(
Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags.None,
"Foo",
null,
new[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) }
)
);
site.Target(site, x, 42);
Console.WriteLine(((dynamic)x).Foo);

Reflection over object dynamic view properties

D-Stanley comment pointed me in the good direction. I found the solution following couple links from there. Didn't had the exact same problem but close enough and it solved mine.

Solution here : Reflection with IDispatch-based COM objects

Dynamic Property to list in c# from reflection

You can convert with a function like this.

If the reflected object is not enumerable, it can't be converted.

public static List<T> ConvertMysteriousObjectToList<T>(object input)
{
var enumerable = input as IEnumerable;
if (enumerable == null) throw new InvalidOperationException("The object is not convertible to a list.");
return enumerable.Cast<T>().ToList();
}

If you're trying to convert some flavor of DbSet (e.g. a DbSet<Foo>) then you'd call it like this:

var o = ClassObject.GetType().GetProperty(classname);
var list = ConvertMysteriousObjectToList<Foo>(o);

If you don't know the type:

var list = ConvertMysteriousObjectToList<object>(o);

or

var list = ConvertMysteriousObjectToList<dynamic>(o);

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

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

Get properties of a Dynamic Type

You can use reflection to get the properties out and convert it to a dictionary:

dynamic v = new { A = "a" };

Dictionary<string, object> values = ((object)v)
.GetType()
.GetProperties()
.ToDictionary(p => p.Name, p => p.GetValue(v));

Cast dynamic object to type using reflection c#

You can't cast a dynamic object to a specific type, as @Lasse commented.

However, your question mentions "reflection", so I suspect you're looking for a way to simply map property values (i.e. "creating a new X and copying over values, etc." in Lasse's comment):

...
myDynamic.A = "A";

// get settable public properties of the type
var props = currentType.GetProperties(BindingFlags.Public | BindingFlags.Instance)
.Where(x => x.GetSetMethod() != null);

// create an instance of the type
var obj = Activator.CreateInstance(currentType);

// set property values using reflection
var values = (IDictionary<string,object>)myDynamic;
foreach(var prop in props)
prop.SetValue(obj, values[prop.Name]);


Related Topics



Leave a reply



Submit