Dynamic properties of DI in Unity

Mar 14, 2008 at 8:45 AM
Hi, Unityers,

I posted a question on the EntLib forum two days ago, but it seems I should have used this forum. I am reproducing it below, hoping to get some response here as well. The issue is how to model a system where the set of (injectable) services can change all the time. Copy/paste begins:

Hi, folks,

I am completely new to EntLib (and .NET as well in fact), but I'm familiar with dependency injection. In my previous project, we implemented a DI mechanism on top of the OSGi Module System, and made it work seamlessly across multiple VM's.

OSGi is a very dynamic environment, in which services can appear, disappear and reappear without further notice. The DI mechanism had to handle (re)appearing services by registering listeners in OSGi. Incidentally, our framework also handled the opposite of injection, exposing a service, so that when all your dependencies were satisfied, your own service(s) were exposed, so that they became candidates for injection into other components - and so on. If your dependencies were lost later (e.g. if a machine went down), your service might get unexposed, which might take away a dependency for someone else - and so on. In short, in this environment, the work of the DI framework is never done.

Before that, I used the Spring framework. Spring was, at least back then, static in comparison - the basic usage pattern was to have Spring wire everything up as configured, and then start up. It did not have much in the way of a runtime API, or dynamic "uninjection" of services. This works well for webapps and tiered applications with well-known dependency structures.

So when getting to grips with EntLib, my approach is to find out where it lies in relation to these two extremes. We are making a system that might be very dynamic - in fact, we're porting the OSGi-based one I'm referring to - how would EntLib fit with that? Which elements of the EntLib design have more or less of that degree of dynamic freedom between them? Should I be using something else? (We may not have all the freedom we would like wrt. third-party/open-source libraries on the project.)

Thanks for everybody's time,

Kjetil (yes, I am reading up on the code base, too, but I find it is often worthwhile to get those larger questions out there as well)

Mar 14, 2008 at 12:37 PM
Just to head off further confusion: By "EntLib" in the above, I am referring to the upcoming version, the one with Unity.
Mar 15, 2008 at 4:50 AM
Well, Unity does not aspire to be anywhere that dynamic, and neither does Entlib. It's probably closer to what you've seen in Spring than in OSGi. Although I must admit I'm not familiar with that platform.

How do object clients respond to services that go away? With Unity and Entlib in general, it's assumed that once you've got an object instance it'll stay around until you're done with it?
Mar 15, 2008 at 11:32 AM

ctavares wrote:
How do object clients respond to services that go away? With Unity and Entlib in general, it's assumed that once you've got an object instance it'll stay around until you're done with it?


Thanks for replying, ctavares, and for corroborating my initial findings.

When a service goes away, the framework tells the client about this, as a lost dependency (basically invoking the setter with null, or a designated "remove" method). The client may be on a contract with the framework (implemented via attributes on annotations/metadata) that says the dependency was in fact a requirement for operating. The framework manages the client's state and demotes it to non-active state, invoking pre-defined callbacks on it along the way.

In the rainy-day scenario, the dependency goes away (a remote process dies, say) while the client is using it. The framework does not insulate the clients against this, for efficiency reasons (objects are wired up with direct references to each other, to avoid overhead), so the usual rules for exception handling apply. (If it was a remote reference, the framework does of course insulate against low-level I/O exceptions, and conveys the real exception.) A well-designed system (designed on top of this framework) will have some sort of centralized exception handling. If the exception occurs in the dispatch thread of the framework and comes out of the callback method of a component, that component will be deactivated and taken to the FAILED state. This is pretty bad, since any component using its services will be deprived of their dependencies.

I think Unity could be a base for such a system, provided it has a good API for programmatically altering the set of managed objects - i.e. registering services - and listening for such change events. For reference, OSGi did provide us with a Service Registry with these features, and it is enough to build in a lot of dynamcs. Spring's internal did not lend themselves (as I remember them) to runtime tinkering, it was more of a wire-up-and-press-play type of situation.
Mar 19, 2008 at 4:21 AM

OSGi is a very dynamic environment, in which services can appear, disappear and reappear without further notice. The DI mechanism had to handle (re)appearing services by registering listeners in OSGi. Incidentally, our framework also handled the opposite of injection, exposing a service, so that when all your dependencies were satisfied, your own service(s) were exposed, so that they became candidates for injection into other components - and so on. If your dependencies were lost later (e.g. if a machine went down), your service might get unexposed, which might take away a dependency for someone else - and so on. In short, in this environment, the work of the DI framework is never done.


Kjetil, I suggest you will look at Windsor for that.
It is pretty easy to get that scenario working for you (you need to create customer naming subsystem, basically).
And handling the exposure of additional services based on others coming alive is already handled for you (see Startable for details).

However, I wouldn't suggest dynamically adding/removing services, I would suggest proxying the services, and replacing their backend behind the scenes.
The reason for that is that this way you can replace a service even on a resolved component.
Imagine something like this:

IMyService srv = IoC.Resolve<IMyService>();
// here we lose some services that 'srv' is using.
srv.DoSomething(); // now we can do something intelligent with that lose.
Mar 19, 2008 at 11:55 AM
Hi, and thanks. We could look more into Windsor, but we're a little worried that political (a.k.a. architectural, for certain values of architect) issues might prevent us from using a third-party library. However, it is useful to know that more technically promising solutions might be lying in that directon.


Ayende wrote:
However, I wouldn't suggest dynamically adding/removing services, I would suggest proxying the services, and replacing their backend behind the scenes.
The reason for that is that this way you can replace a service even on a resolved component.


Except that the component might hit the proxy while it is re-resolving, too. This works on stateless calls by having the proxy block the request and respond when ready. The general "re-resolve" issue had not been sufficiently explored by the time of port, but we might have done something like this for all non-performance-critical, stateless services. But the constraints on this system was to allow direct links, to preserve performance. An extra layer of indirection on all edges of the graph would compromise the high performance required, so
Mar 19, 2008 at 2:50 PM
Performance is not an issue.
The cost of indirection is a single extra method call + whatever processing that you want to make.