We handled this by using field mapping rather than property mapping (field.camelcase-underscore), with the field that NHibernate sees feeding a private property with a different name. Then the public property whose name does match the field is of our collection type, which uses the composition design pattern to forward to the underlying collection.
So, an example looks like this:
Code:
public class Contact
{
private IList _addresses;
private OurListType<Address> _addressesTyped;
public virtual OurListType<Address> Addresses
{
get
{
if (this._addressesTyped == null)
{
this._addressesTyped = new OurListType<Address>(this.AddressesUntyped, ...);
}
else if (!object.Equals(this._addressesTyped.InnerList, this.AddressesUntyped)
{
this._addressesTyped.InnerList = this.AddressesUntyped;
}
return this._addressesTyped;
}
private IList AddressesUntyped
{
get
{
if (this._addresses == null)
{
this._addresses = new ArrayList();
}
return this._addresses;
}
}
...
}
Then OurListType can provide whatever it wants -- we implement IList, IList<T>, IBindingListView, IComparer, etc. Our list type tracks the property name on the item class that references the owner of the list (the "parent"), and automatically sets/clears it when items are added/removed from the list.