Home

Code Beauty : Dynamic Type Properties for a PropertyGrid

February 10, 2013

When you build an Editor, there’s always one thing you are going to need : a good property editor.

For that, I’ve chosen the one in Extended WPF Toolkit and it behaves quite nicely. But then it got tricky. In my engine, one does not simply walk set a property like that. I have that kind of structure:

 /// <summary>
 /// ...
 /// </summary>
 public GeometryMaterial GetGlobalMaterialOverride(ModifierReference reference)
 {
...
 }

/// <summary>
 /// ...
 /// </summary>
 public void SetGlobalMaterialOverride(ModifierReference reference, GeometryMaterial material)
 {
...
 }

Thus, giving it to the property grid produces no result.

So what can we do ? The propertygrid is expecting an object with properties for each thing we want to display. So let’s generate it !


PropertyBuilder propertyBuilder = typeBuilder.DefineProperty(prop.Key, PropertyAttributes.None, prop.Value.PropertyType, Type.EmptyTypes);

if (prop.Value.GetMethod != null)
 {
 MethodBuilder getMethodBuilder = typeBuilder.DefineMethod("get_" + prop.Key, MethodAttributes.Public, CallingConventions.HasThis, prop.Value.PropertyType, Type.EmptyTypes);
 ILGenerator getter = getMethodBuilder.GetILGenerator();
 getter.Emit(OpCodes.Ldarg_0);
 getter.Emit(OpCodes.Ldstr, prop.Key);
 getter.Emit(OpCodes.Callvirt, typeof(DynamicServicingObject).GetMethod("Get", BindingFlags.Instance | BindingFlags.NonPublic).MakeGenericMethod(prop.Value.PropertyType));
 getter.Emit(OpCodes.Ret);
 propertyBuilder.SetGetMethod(getMethodBuilder);
 }

if (prop.Value.SetMethod != null)
 {
 MethodBuilder setMethodBuilder = typeBuilder.DefineMethod("set_" + prop.Key, MethodAttributes.Public, CallingConventions.HasThis, typeof(void), new Type[]{prop.Value.PropertyType});
 ILGenerator setter = setMethodBuilder.GetILGenerator();
 setter.Emit(OpCodes.Ldarg_0);
 setter.Emit(OpCodes.Ldstr, prop.Key);
 setter.Emit(OpCodes.Ldarg_1);
 setter.Emit(OpCodes.Callvirt, typeof(DynamicServicingObject).GetMethod("Set", BindingFlags.Instance | BindingFlags.NonPublic).MakeGenericMethod(prop.Value.PropertyType));
 setter.Emit(OpCodes.Ret);
 propertyBuilder.SetSetMethod(setMethodBuilder);
 }

We are making a new type using TypeBuilder, adding our properties for each method matching the pattern “GetStuff” and “SetStuff”, link it to our original object by specifying our generated instance as the grid target, and voilà !

PropGenerator

Original idea : Stackoverflow

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: