Hello forum members,
I would like to start a thread for adding dynamic ITypedList support to the default collections of Nhibernate. This would make databinding life to certain WinForm controls a lot easier, I’m thinking DevExpress XtraGrid but there must be others as well.
The problem with these grids lies in the fact that they don’t use ‘real’ databinding.
On a textbox you do:
Code:
textBox1.DataBindings.Add(new Binding("Text", employeeList, "Employee.Department.Organization.Name"));
In this case the .Net engine takes care of the . path, all goed well and there is great rejoice among the people.
But there are certain controls that don’t use this, they assume that the underlying datasource is flat and if you try to resolve ‘Employee.Department.Organization.Name’ it does this without taking care of the dots, i.e. you get an exception that this property doesn’t exists.
I’ve made a sample implementation on an dynamic ITypedList generator of which there is a piece of code included below.
It works by scanning for properties on the base object (typeof(T)) of an IList<> collection. It then creates a custom property descriptor that uses reflection to get to the real property and is capable of handling the dot pattern style paths.
The main problem with this approach is that you have to pre-generating all the paths. I use a recursive function, which could easily span across your entire object model and you have to take care of Parent/Child relations as they tend to end up in a Stackoverflow exception.
This is now done in a very rude way by limiting the depth of the scan to a fixed number (50 in my test case, but this could be way too big… or perhaps too small, who’s to say :) ).
I would very much appreciate any comments, thoughts and other ideas on this subject and the code!
Kind regards,
Ernst Naezer
Code:
<snip>
private List<PropertyDescriptor> ScanProperties(Type root, string path, int depth)
{
if (depth > 50) return null; // hmm
List<PropertyDescriptor> propertyList = new List<PropertyDescriptor>();
// get the properties of the root type
PropertyDescriptorCollection propertyCollection = TypeDescriptor.GetProperties(root);
// walk them
foreach (PropertyDescriptor property in propertyCollection)
{
// contstruct the dot pattern path
string propertyPath = string.Format("{0}{1}{2}", path, path != string.Empty ? "." : string.Empty, property.Name);
propertyList.Add( new RecursivePropertyDescriptor( propertyPath , root.GetProperty(property.Name)));
// here we jump into recursion
List<PropertyDescriptor> scanResult = ScanProperties(property.PropertyType, propertyPath, depth + 1);
if ( scanResult != null)
propertyList.AddRange(scanResult);
}
return propertyList;
}
public System.ComponentModel.PropertyDescriptorCollection GetItemProperties(System.ComponentModel.PropertyDescriptor[] listAccessors)
{
Type root = typeof(T);
if ( listAccessors != null )
root = listAccessors[ listAccessors.Length - 1 ].PropertyType;
return new PropertyDescriptorCollection(ScanProperties(root,string.Empty, 0).ToArray());
}
</snip>
Please note that this isn’t the complete code only the recursive scan and a piece of the ITypedList interface. I haven't applied this code to the NH collection only extended an BindingList<> class in a save winforms project, but I'm guessing it also works inside NH.