Is there an NHibernate equivalent of [OnDeserialized] (not [OnDeserialization])?
I am working on a project using NHibernate. Many of our business objects have internal collections, where updating the collection causes side-effects in other objects (e.g., a when a one-to-many relationship is modeled as a collection on the “one” side and a back reference on the “many” side, and the relationship requires modifying both sides to keep things consistent) or other objects’ collections (e.g., when a many-to-many relationship is modeled as two one-to-many relationships, similarly with a consistency requirement). Other objects can request the business objects to modify these internal collections, and frequently these internal collections need to be observable (implement INotifyCollectionChanged). There are three approaches that seem at first glance to be viable:
1. Publish the internal collection as a property;
2. Implement the ICollection<T> and INotifyCollectionChanged interfaces on the business object itself, and implement ICollection<T> methods that delegate to the internal collection and fire the NotifyCollectionChanged event as appropriate.
3. Implement AddToXyzzyCollection(), RemoveFromXyzzyCollection, ClearXyzzyCollection(), NotifyXyzzyCollectionChanged, and so forth, methods and properties, and delegate to the appropriate method of the appropriate internal collection.
Alternative (3) is surpassingly ugly, and I believe should be avoided if at all possible.
Alternative (2) seems cumbersome, particularly when a business object has several internal collections—and is unusable if two of those internal collections happen to be collections of a single element class.
Alternative (1) therefore seems most desirable: we publish the collections as a property, and let client objects add and remove elements and collection change observers as they wish. Now, to keep the various collections and references straight, the business object has to itself subscribe to the NotifyCollectionChanged event of the internal collection, so that it can propagate changes as required. (That is, if some client object removes a BaseLocation from a GeographicArea’s collection, I need to clear the GeographicArea property of that BaseLocation.) Similarly, if the business object is to control clients’ abilities to modify its internal collections, the internal collections need to call back to the business object for permission to perform an incipient modification—a “NotifyCollectionAboutToBeChanged” event, if you will.
Now, both of these require the business object to update the internal collection’s delegates. This must happen after the internal collection is constructed. So either (i) the internal collection’s various delegates must survive saving and loading with NHibernate, (ii) the internal collection’s various delegates must be restored by the business object after NHibernate has loaded the object, or (iii) the internal collection must in fact be several collections—delegate lists and the desired collection itself—and each of the delegate lists and the collection itself are separately saved and restored.
I can’t see a way to do (i). I also can’t see a way to do (ii)—a load interceptor delegating to a “hook things up” method in the object is almost possible, but load interceptors are called before construction, rather than after. And I can’t see a way to do (iii)—NHibernate seems not to document a way to save and restore a delegate (a list of methods, rather than objects).
So it seems alternative (3), implement AddToXyzzyCollection() and its many friends and relations, is about the best that can be done. Unless there is some post-load, pre-use hook—the NHibernate equivalent of either IDeserializationCallback or [OnDeserialized]. I can’t find one. Does one exist?
|