Preventing Duplicate Type Registrations

Mar 27, 2009 at 2:21 AM
Hello,

I'm pretty new to Unity, and I have a question.

Suppose I register a concrete type with the container:

container.RegisterType<ILogger, ConsoleLogger>(new ContainerControlledLifetimeManager());

It appears that Unity will allow me to override this setting at a later point in time:

container.RegisterType<ILogger, FileLogger>(new ContainerControlledLifetimeManager());

Is there any way I can prevent these duplicate registrations?  My immediate throught is to extend the UnityContainer by creating a derived class to prevent the above from happening and throwing an exception if it does.  Are there any simpler ways to do this?

I'm trying to build a framework for a composite application.  I wouldn't want the various modules that comprise the composite app to be overriding any of the registrations that have been set up by the shell.  Of course, they can create a child container, or register the interface under a different name, but I need to find a way to prevent them from overriding a preexisting registration.

Thanks for any insight / help!



Mar 27, 2009 at 3:59 AM
The "last one wins" behavior was a deliberate design decision, so there's no built-in support for disabling it. However, another option would be to use it to your advantage.

What if your shell registered its services after the modules registered their types? That way, the shell registration is guaranteed to be the one in the container, regardless of what the modules did.

Apr 6, 2009 at 11:24 PM
In my opinion this violates the Principle of Least Astonishment. Within the context of a composite application (e.g. Prism), if a user attempts to register a type from within their module then I submit that the expected behavior would be either that the type registration would fail, or that a successful resolution would result in the expected instance.

Fortunately, this particular design decision can probably be easily dealt with by writing a custom Extension which provides the ability to globally or by type configure the preexisting registration behavior (e.g. ThrowException, Ignore, Replace, etc.)