We do the following to support typed collections. The example shows a Contact class with a collection of ContactAddress objects. Contact and ContactAddress map to a table, but the ContactAddress collection class does not.
Code:
public class Contact
{
// Accessed directly by NHibernate;
// must be named the same as the typed public property
// except using camelcase-underscore
private IList _addresses;
private ContactAddressCollection _addressesTyped;
public virtual ContactAddressCollection Addresses
{
get
{
if (this._addressesTyped == null)
{
// first access of strongly typed collection;
// wrap weakly typed collection used by NHibernate
this._addressesTyped = new ContactAddressCollection(this._addresses, ...);
}
else
{
// Reassign the weakly typed collection to the typed collection
// just in case NHibernate recreated it ...
this._addressestyped.ExternalCollection = this.AddressesUntyped;
}
return this._addressesTyped;
}
}
// Used only by public typed collection property
private IList AddressesUntyped
{
get
{
if (this._addresses == null)
{
// Initialize it in case NHibernate hasn't set it yet
this._addresses = new ArrayList();
}
return this._addresses;
}
}
}
<hibernate-mapping
...
<class name="Contact" ... >
...
<bag name="Addresses" inverse="true" lazy="true" cascade="all-delete-orphan" access="field.camelcase-underscore">
<key column="..." />
<one-to-many class="ContactAddress"/>
</bag>
</class>
</hibernate-mapping>
Because of the bag's access of "field", Nhibernate only cares about the weakly typed field, but my property of the same name is strongly typed, so my code and HQL queries can use the property name as expected. From what we can tell so far, it works great.
Our strongly typed collections have a settable property called ExternalCollection, plus a bunch of other stuff to enforce the correct type, track what entity instance the collection belongs to, track the name of the "parent" property on the contained item's type in order to automatically set/clear it when items are added/removed from the collection, raise events before and after items are added/removed, "freeze" the collection so no more items can be added or removed, define arbitrary rules validating an item being added to the collection (based on what's already in it), etc.