views:

86

answers:

3

Hi Guys,

I'm relatively new to dependency injection, so I'm probably butchering the concept to some extent. However, I'm trying to achieve something like the following, but am unsure as to whether or not it's feasible:

Lets say I have two containers, each containing different instances of the same type of dependency. For example, each contains a different single instance of MyApplicationContext and MyRequestContext.

Now lets say I have several classes which depend on one (or both) of these instances. They shouldn't be concerned with which of the two containers they use; they simply require an instance of the dependency to get the job done.

In an ideal world, each of these dependable classes makes a static call in its constructor, which in turn reflectively injects the dependencies from an appropriate container...

public class MyDependableClass{
  protected MyApplicationContext Application {get; set;}
  protected MyRequestContext Request {get; set;}
  public MyDependableClass() {
    Dependencies.Inject(this);
  }
}

However, AFAIK there's no practical way of determining an appropriate container. I've considered registering each object against a particular container (e.g. container.Register(obj); ), but this would be laborious and wouldn't work if dependencies were required in the constructor. Alternatively you could analyze the call stack to infer the container from a registered top-level object... wouldn't work for asynchronous calls, etc

Any ideas?

Example: I may have several classes which can depend on an instance of a proxy; let's call it ILogicProxy. This proxy may forward calls to either local logic or remote logic on another machine. Furthermore, the application may establish connections with several remote machines. So... we have potentially multiple ILogicProxy instances which need to be injected into several classes... but which one goes where? A solution like this could just use simple 'setter property injection', however this doesn't scale when more dependencies are required, since it will cause the 'wiring up' process to become messy/verbose.

A: 

i'm new to dependency injection too, the book i'm reading (about mvc2) uses ninject for dependency injection. You might give it a try or see hoe it does this task .

Stefano
Thanks for the suggestion Stefano. I had a brief look at this framework (and others), but they all seem to follow the 'singleton' or 'single-container' pattern. They can't (to my knowledge) do what I'm suggestion above, whereby you can have multiple groups of dependencies to achieve a 'multiton' pattern.
Lawrence
+1  A: 

This isn't a case for multiple containers. Use the container configuration to wire things up. If you have a large number of components registered under the ILogicProxy interface, then yes, you'll have to do more manual wiring. But ask yourself if these components should be really registered under the same interface.

About the code sample:

In an ideal world, each of these dependable classes makes a static call in its constructor, which in turn reflectively injects the dependencies from an appropriate container...

public class MyDependableClass{
  protected MyApplicationContext Application {get; set;}
  protected MyRequestContext Request {get; set;}
  public MyDependableClass() {
    Dependencies.Inject(this);
  }
}

This is service location, not dependency injection. Always prefer dependency injection to service location. Try not to depend on Resolve() or Inject() methods in your components.

Mauricio Scheffer
Thanks Mauricio. I vaguely remember service location from my Java days at Uni, and yes I agree, my sample has more of a resemblance of this method.However, configuration files are static, meaning that I cannot make the dependency->dependable associations at instance level, as I am only able to make the association at definition level. E.g. I want 'InstanceA depends on InstanceB', not 'ClassA depends on ClassB'.
Lawrence
@Lawrence: can you elaborate on "configuration files are static"? maybe post some code?
Mauricio Scheffer
A: 

It seems to me that you don't need multiple containers, but that you have to create an implementation of ILogicProxy that knows how to route. You could perhaps implement that type as a wrapper around other ILogicProxy implementation, like this:

public class LogicProxyRouter : ILogicProxy
{
    private readonly ILogicProxy local;
    private readonly ILogicProxy remote;

    public LogicProxyRouter(ILogicProxy local, ILogicProxy remote)
    {
        this.local = local;
        this.remote = remote;
    }

    public void Method(params)
    {
        if (someCondition)
        {
            this.local.Method(params);
        }
        else
        {
            this.remote.Method(params);
        }
    }
}

This way you can hook up a single instance like this:

ILogicProxy proxy =
    new LogicProxyRouter(new LocalLogicProxy(), new RemoteLogicProxy());

// Register that instance in your favorite IoC framework
container.RegisterSingle<ILogicProxy>(proxy);

I hope this helps.

Steven