Skip to main content

Microsoft Silverlight

Answered Question Databind object with "dynamic" propertiesRSS Feed

(0)

VFC
VFC

Member

Member

2 points

26 Posts

Databind object with "dynamic" properties

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

nyhetsgrupper@gmail.com
nyhetsgr...

Participant

Participant

1372 points

320 Posts

Answered Question

Re: Databind object with "dynamic" properties

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

Please click the "Mark as answer" link if this answered your question

Roger Gullhaug

VFC
VFC

Member

Member

2 points

26 Posts

Re: Re: Databind object with "dynamic" properties

 Thanks Roger, I have implemented a little bit of code which emit IL on runtime to generate dynamic types.

Aquilax
Aquilax

Member

Member

43 points

37 Posts

Re: Re: Databind object with "dynamic" properties

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 PropertyType
public 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
IDynamicPropertiesHandler
public interface IDynamicPropertiesHandler
{
T GetValue(string name, int index);
void SetValue(string name, int index, T value);
}
#endregion
#region
DynamicTypeGenerator
public 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
 

  • Unanswered Question
  • Answered Question
  • Announcement
Microsoft Communities