I have a custom collection that wraps a .net HashSet and implements ICollection, which I then map as a set. I did this in the hope that NHib would be able to use the ICollection interface to the way it can do when using just a .net HashSet, as opposed to the Iesi one that NHib uses internally.
The save to the db seems to be working fine, but the exception I get when hydrating lets me know I need to do more:
Unable to cast object of type 'NHibernate.Collection.Generic.PersistentGenericSet`1[ContactMechanisms.Domain.Emails.Email]' to type 'ContactMechanisms.Domain.Emails.EmailCollection'.
These articles are frequently cited as ways to deal with custom collection handling, but the links are broken and what I can see deals more with querying the collection with extensions.
Must I use an IUserCollectionType? Anyone have a link showing a sample implementation if so? Is there something silly I am doing in my current code / mapping?
What's a good solution?
CODE (parent entity snippet)
public class Contact : RoleEntity<Party>, IHaveContactMechanisms
{
private readonly ICollection<Email> _emails = new EmailCollection();
public virtual EmailCollection Emails { get { return (EmailCollection) _emails; } }
}
CODE (custom collection snippet)
public class EmailCollection : ContactMechanismSet<Email> { .... }
public class ContactMechanismSet<T> : ValueObject, ICollection<T> where T : ContactMechanism
{
private readonly HashSet<T> _set = new HashSet<T>();
}
MAPPING (hbm value type collection)
<set name ="_emails" table="Emails" access="field">
<key column="ContactId"></key>
<composite-element class="ContactMechanisms.Domain.Emails.Email, ContactMechanisms.Domain">
<property name="IsPrimary" />
<property name="Address" length="100"/>
<property name="DisplayName" length="50"/>
</composite-element>
</set>
* UPDATE *
SO doing the below in my object setter works, but - can I do better??
public virtual EmailCollection Emails {
get {
if (!(_emails is EmailCollection )) {
// NHibernate is giving us an enumerable collection
// of emails but doesn't know how to turn that into
// the custom collection we really want
//
_emails = new EmailCollection (_emails );
}
return (EmailCollection ) _emails ;
}
}
if EmailCollection has a parameterless constructor then the following should be possible with newer NH ootb and older with registering CollectionTypeFactory which handles .NET ISet (can be found in internet)