views:

1268

answers:

6

I'm using the Unity IOC container and I'm just wondering what is the best best way to access the container for multiple classes.

Should every class have an IUnityContainer member and then pass the container in by constructor? Should there be a singleton class with an IOC container?

How about asp.net development?

Could somebody guide me in the right direction? Thanks.

+2  A: 

you can register the container in itself and have it injected like every other dependency property, like so:

IUnityContainer container = new UnityContainer();
container.RegisterInstance<IUnityContainer>(container);

classes that need to access it will have the following property:

private IUnityContainer unityContainer;
[Dependency]
public IUnityContainer UnityContainer
{
    get { return unityContainer; }
    set { unityContainer = value; }
}

thus, the container is injected whenever an instance of such a class is resolved/built up.

This is more flexible as it works for multiple containers within the same application, which would not be possible with the singleton pattern.

lcvinny
+1  A: 

If all of your objects need a reference to the container then you should look into reworking the code some. While still preferable to calling new everywhere it still scatters the responsibility of building your object graphs throughout your code. With that kind of usage it strikes me as being used more like a ServiceLocator instead of a IoC Container.

Jeremy Wilde
The application I'm working on uses Com+ for all data access. I've been using the IOC container to instantiate these objects so I can put in a test double if need be
Ryu
So the way I'm doing things I'd have to have all data access limited to one class with also has the IOC container which is hard to do.
Ryu
A: 

Another option would be using the CommonServiceLocator, although it may be a pointless indirection, you may use the ServiceLocator.Current as the instance known by all classes

t3mujin
A: 

I have a post on this subject at my blog where I´m using something along the lines of t3mujin answer. Feel free to use it (don´t bother that it´s sharepoint related...that doesn´t matter):

http://johanleino.spaces.live.com/blog/cns!6BE273C70C45B5D1!213.entry

Johan Leino
+5  A: 

Put the IOC container at the highest level / entry point in the process and use it to inject dependencies in everything underneath it.

Ryu
+4  A: 

IMHO it is not advisable to inject the entire container into a class or to have an application wide static IoC service locator.

You want to be able to see from the constructor of a class (lets call it Foo), what kind of services/objects it is using to get the work done. This improves clarity, testability and degubability.

Lets say Foo only needs the email service, but I pass in the whole container and somewhere in the code the email service gets resolved from the container. In this case it will be very hard to follow. Instead it is better to inject the email service directly to state Foo's dependencies clearer.

If Foo needs to create multiple instances of the email service, it is better to create and inject an EmailServiceFactory (via the IoC container), which will create the required instances on the fly.

In the latter case, Foo's dependencies are still indicated as specific as possible - only the ones, that the EmailServiceFactory can create. Had I injected the whole container, it would not be clear what services provided by it are Foo's exact dependencies.

Now, if I later want to provide different instances of the email service, I swap it out inside the EmailServiceFactory. I could swap out the whole factory as well, if all the services it creates need to be swapped (e.g. during testing).

So at the cost of creating one extra class (the factory), I get much cleaner code and won't have to worry about curious bugs that may occur when global statics are used. Additionally when supplying mocks for testing, I know exactly what mocks it needs and don't have to mock out an entire container's types.

This approach also has the advantage, that now, when a module is initialized (only applies to Prism / Modularity), it doesn't have to register all of the types of objects it supplies with the IoC container. Instead it can just register its ServiceFactory which then supplies those objects.

To be clear, the module's initialization class (implements IModule) should still receive the application wide IoC container in its constructor in order to supply services, that are consumed by other modules, but the container should not invade into the module's classes.

Finally, what we have here is another fine example of how an extra layer of indirection solves a problem.

Thorsten Lorenz