I have two POCO types, A and B. I have a repository for each, Rep<A> and Rep<B>, both of which implement IRep<A> and IRep<B> served up by an IoC container (AutoFac in this case).
There are several kinds of repositories – load-on-demand from a DB (or whatever), lazy-loaded in-memory collections, cached web-service results, etc. Callers can’t tell the difference. Both Rep<A> and Rep<B> happen to be in-memory collections as A’s and B’s don’t change very much and live a long time.
One of the properties of B is an A. What I do now is, when a B is asked for its A, B gets IRep<A> to find its A and returns it. It does this every time – every request for B’s A involves IRep<A>.Find(). The upside is B’s never hold onto A’s and each request takes into account whatever the state of Rep happens to be. The downside is a lot of IoC/IRep<A> churn.
I am thinking of using the Lazy<T> pattern here so that a B asks IRep<A> once and holds onto what it got. But what happens if an A is deleted from its repository?
I am looking for a clean way for Rep<A> to notify whoever is interested when it has changed. In my example, a certain B’s A may be deleted, so I would like Rep<A> to raise an event when something is deleted, or added, etc. Rep<B> might subscribe to this event to clean up any B’s that refer to A’s that are now gone, etc. How to wire it up?
Ideally nothing changes when instantiating a Rep<A>. It should have no idea who listens, and A’s might be manipulated all day long without ever firing up a Rep.
But when Rep<B> is born it needs a way to subscribe to Rep<A>’s event. There might not be a Rep<A> alive yet, but surely there will be once a B is asked for its A, so it seems ok to fire up a Rep<A>.
In essense, when Rep<B> is instantiated, it want it to register itself with Rep<A> for the event notification. I don’t want to pollute the IRep<T> interface becaue this shouldn’t matter to anyone outside the Repository layer. And other types of repositories might not have to worry about this at all.
Does this make any sense?
What if you made the
Rep<A>return an “observable” object that can evaluate to an A, and also has a subscribable event that is raised when something about that A changes? Just a thought. This way, you don’t have to have the handlers check to make sure that their A changed; if the event they’re listening for is fired, it concerns their instance and not any other.You might code it as follows:
Now, the consuming code will be notified if the internal reference is changed, or the observable is disposed (which also disposes of the internal reference). To have the observable also notify consuming code if child references of As change, A must itself be observable, firing an event handled by
Observable<T>which will “bubble” it through either ReferenceChanged or a more specific handler such as InstanceDataChanged,(or whatever you want to call it).