Skip to main content
Home Forums Silverlight Programming Silverlight Controls and Silverlight Toolkit Databind object with "dynamic" properties
3 replies. Latest Post by Aquilax on June 29, 2009.
(0)
VFC
Member
2 points
26 Posts
04-16-2009 5:14 AM |
I have to display a collection of values in a DataGrid, the number of the values is dynamic. In .Net I would have implemented the ICustomTypeDescriptor interface and extended the PropertyDescriptor class, but those are not available in Silverlight, moreover taking a look to the implementation of the DataGridDataConnection class, I've seen this:
public PropertyInfo[] DataProperties{ get { if (this._dataProperties == null) && (this.DataSource != null)) { Type dataType = this.DataType; if ((dataType != null) && !DataTypeIsPrimitive(dataType)) { this._dataProperties = dataType.GetProperties(BindingFlags.Public | BindingFlags.Instance); } else { this._dataProperties = null; } } return this._dataProperties; }}
The properties of the datasource are extracted with reflection. So the only way to expose dynamic properties would be to generate a dynamic class on runtime with reflection and assemblybuilder? Or there is another solution?
Regards VFC
nyhetsgr...
Participant
1372 points
320 Posts
04-17-2009 3:11 AM |
You can see this blogpost for another solution: http://jonoporter.blogspot.com/2008/11/dynamic-silverlight-datagrid.html
I have created a sample application using this method:http://cid-f352126e8a8b36c4.skydrive.live.com/self.aspx/.Public/100pctDynamicGrid.zip
04-21-2009 2:49 PM |
Thanks Roger, I have implemented a little bit of code which emit IL on runtime to generate dynamic types.
Aquilax
43 points
37 Posts
06-29-2009 10:07 AM |
I was looking for the same thing, I found some interesting articles:
http://msdn.microsoft.com/en-us/library/system.reflection.emit.propertybuilder(VS.95).aspx
http://devhawk.net/2009/04/24/clrtype+Metaclasses+Adding+CLR+Properties.aspx
http://mironabramson.com/blog/post/2008/06/Create-you-own-new-Type-and-use-it-on-run-time-(C).aspx
My problem was transform an array to an object with x properties, at the end I created a static method to extend a type and add the needed properties. The base type must implement the IDynamicPropertiesHandler interface. The generated properties call the the GetValue and SetValue defined in the IDynamicPropertiesHandler interface. The GetValue and SetValue methods have also an index argument, which is unique for each generated property, this is quite useful for mapping arrays to properties.
#region PropertyTypepublic class PropertyType{ public PropertyType(string name, Type type) { this.Name = name; this.Type = type; } public string Name { get; set; } public Type Type { get; set; }}#endregion#region IDynamicPropertiesHandlerpublic interface IDynamicPropertiesHandler{ T GetValue(string name, int index); void SetValue(string name, int index, T value);}#endregion#region DynamicTypeGeneratorpublic static class DynamicTypeGenerator{ #region Fields & Properties private static int _counter; private static AssemblyBuilder _ab; private static ModuleBuilder _mb; private static AssemblyBuilder AB { get { return DynamicTypeGenerator._ab ?? (DynamicTypeGenerator._ab = Thread.GetDomain().DefineDynamicAssembly(new AssemblyName("DynamicTypeGeneratorAssembly"), AssemblyBuilderAccess.Run)); } } private static ModuleBuilder MB { get { return DynamicTypeGenerator._mb ?? (DynamicTypeGenerator._mb = DynamicTypeGenerator.AB.DefineDynamicModule("DynamicTypeGeneratorModule")); } } #endregion #region ExtendDynamicType public static Type ExtendDynamicType(PropertyType[] properties) where T : IDynamicPropertiesHandler { return DynamicTypeGenerator.ExtendDynamicType(properties, string.Format("DynamicType{0:00}", DynamicTypeGenerator._counter++)); } public static Type ExtendDynamicType(PropertyType[] properties, string extendedTypeName) where T : IDynamicPropertiesHandler { MethodInfo gv = typeof(IDynamicPropertiesHandler).GetMethod("GetValue"); MethodInfo sv = typeof(IDynamicPropertiesHandler).GetMethod("SetValue"); MethodAttributes ma = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName; TypeBuilder tp = DynamicTypeGenerator.MB.DefineType(extendedTypeName, TypeAttributes.Public, typeof(T)); tp.DefineDefaultConstructor(MethodAttributes.Public); for (int num1 = 0; num1 < properties.Length; num1++) { PropertyType pt = properties[num1]; MethodBuilder mbget = tp.DefineMethod("get_" + pt.Name, ma, pt.Type, Type.EmptyTypes); ILGenerator ilGen1 = mbget.GetILGenerator(); ilGen1.Emit(OpCodes.Ldarg_0); ilGen1.Emit(OpCodes.Ldstr, pt.Name); ilGen1.Emit(OpCodes.Ldc_I4, num1); ilGen1.Emit(OpCodes.Callvirt, gv.MakeGenericMethod(pt.Type)); ilGen1.Emit(OpCodes.Ret); MethodBuilder mbset = tp.DefineMethod("set_" + pt.Name, ma, null, new Type[] { pt.Type }); ILGenerator ilGen2 = mbset.GetILGenerator(); ilGen2.Emit(OpCodes.Ldarg_0); ilGen2.Emit(OpCodes.Ldstr, pt.Name); ilGen2.Emit(OpCodes.Ldc_I4, num1); ilGen2.Emit(OpCodes.Ldarg_1); ilGen2.Emit(OpCodes.Callvirt, sv.MakeGenericMethod(pt.Type)); ilGen2.Emit(OpCodes.Ret); PropertyBuilder pb = tp.DefineProperty(pt.Name, PropertyAttributes.HasDefault, pt.Type, Type.EmptyTypes); pb.SetGetMethod(mbget); pb.SetSetMethod(mbset); } return tp.CreateType(); } #endregion} #endregion