Search code examples
c#dependency-injectionunity-container

Injecting parents into composite constructors with Unity C#


I am trying to get IoC working with Unity in C# with the idea of a passing a wrapper/composite class into the children.

The top level class that composes multiple classes provides some common functionality that the composed classes require access to.

To illustrate:

// The top composite class
public class Context : IContext {
  public ISomething SomethingProcessor { get; }
  public IAnother AnotherProcessor { get; }

  public Context(ISomething something, IAnother another) {
    this.SomethingProcessor = something;
    this.AnotherProcessor = processor;
  }

  // A function that individual classes need access to, which itself calls one of the children.
  public string GetCommonData() {
    return this.AnotherProcessor.GetMyData();
  }
}

public class Something : ISomething {
  private _wrapper;
  public Something(IContext context) {
    this._wrapper = context;
  }

  // This class has no knowledge of IAnother, and requests data from the master/top class, which knows where to look for whatever.
  public void Do() {
    Console.WriteLine(_wrapper.GetCommonData());
  }
}

public class Another : IAnother {
  public string GetMyData() {
    return "Foo";
  }
}

If you didn't use IoC, it's easy, as the constructor for the Context class becomes:

public Context() {
  this.SomethingProcessor = new Processor(this);
  this.AnotherProcessor = new Another();
}

But when you're using IoC, the idea of "this" doesn't exist yet because it is yet to be constructed by the injector. Instead what you have a is a circular dependency.

container.RegisterType<ISomething, Something>();
container.RegisterType<IAnother, Another>();
container.RegisterType<IContext, Context>();

var cxt = container.Resolve<IContext>();  // StackOverflowException

The above example has been greatly simplified to illustrate the concept. I'm struggling to find the "best practice" way of dealing with this kind of structure to enable IOC.


Solution

  • I don't know the name of this pattern, or even if it is a bad or good practice, but you can solve your problem of "double-binding" by creating a method to bind the "IContext", instead of doing it in the constructor.

    For instance,

    1) ISomething has a void BindContext(IContext context) method

    2) You implement it as such :

    class Something : ISomething 
    {
       IContext _wrapper;
    
       // ... nothing in constructor
    
       public void BindContext(IContext context)
       {
            _wrapper = context;
       }
    }
    
    

    3) Remove the IContext dependency injection in Something constructor.

    And you call it from the context constructor :

    public Context(ISomething something, IAnother another) {
        this.SomethingProcessor = something;
        this.SomethingProcessor.BindContext(this);
    
        // same for IAnother
    }
    

    And you do the same for IAnother. You could even extract some common interface "IBindContext" to make things a beat more "DRY" (Don't Repeat yourself) and make IAnother and ISomething inherit from it.

    Not tested, and again : not sure it's the best way to do such dependency design. I'll be glad if there is another answer which gives a state-of-the-art insight about this.