Lawrence
Lawrence

Reputation: 51

.NET Reflective Dependency Injection with Multiple Containers

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.

Upvotes: 2

Views: 1439

Answers (2)

Steven
Steven

Reputation: 172855

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.

Upvotes: 0

Mauricio Scheffer
Mauricio Scheffer

Reputation: 99750

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.

Upvotes: 1

Related Questions