11

I have a base Class Base having dependecy Dep and default and Injection Constructor-

Class Base : IBase
 {

    public IDep Dep { get; set; }

    public Base()
    {
        Console.WriteLine("Default Constructor Base ");
    }

    [InjectionConstructor]
    public Base(IDep dep)
    {
        Console.WriteLine("Injection Constructor Base ");
        Dep = dep;            
    }
}

I thought that Dependency dep should get injected automatically(through Constructor Injection) when derived class is resolved.

But this doesnt seem to work when I derive a class from it and Resolve that class, Instead a default Constructor of Base being called.

I can only get this to work when I explicitly call the constructor from the Derived Class.

class Derived : Base
{

    public Derived ()
    {
        Console.WriteLine("Default Constructor Derived ");
    }

    public Derived (IDep dep) : base(dep1)
    {
        Console.WriteLine("Injection Constructor Derived ");            
    }
}

Does unity provide any direct way to implicitly call the injection Constructor of base class (not by explicit Construtor call)? If not, Is there any reason that why unity container is not doing by itself??

Rajat Srivastava
  • 173
  • 1
  • 1
  • 8
  • Your problems are caused by having multiple constructors. Your services should only have one single constructor. Having [multiple constructors is an anti-pattern](https://www.cuttingedge.it/blogs/steven/pivot/entry.php?id=97) and it should be avoided. – Steven Sep 13 '14 at 09:37
  • @Steven I got your point that multiple constructors is an anti-pattern. But removing the Default constructor does not resolve the purpose here. – Rajat Srivastava Sep 14 '14 at 15:58
  • I think it actually resolves your problems, because if both `Base` and `Derived` contain each just one constructor that takes in the required dependencies, the problem wont exist at all. I do agree however with @BatteryBackupUnit that having a base class might not be the best design. – Steven Sep 15 '14 at 09:52
  • @Steven [Should we always include a default constructor in the class](http://stackoverflow.com/questions/3692042/should-we-always-include-a-default-constructor-in-the-class) . I cannot have a Parametrized Constructor without defining a Default Constructor. – Rajat Srivastava Sep 16 '14 at 12:33
  • @Steven Even if i skip the Default Constructor in the base class my derived class constructor will give the compiler error. – Rajat Srivastava Sep 16 '14 at 12:39

3 Answers3

18

No, unity is unable to do so. Actually, there's not a single container who can do so. A constructor is there to instantiate a class. If you call two constructors, you'll end up with two instances. If the base class is abstract, you couldn't even call its constructor (except derived constructors as you know).

So by limitations of C#.net, if you want to use constructor injection, it will only work if you explicitly inject the value into the Derived constructor which calls the non-default Base constructor.

However, you might choose to use Property or Method injection instead. With these you don't have to add the dependency to every constructor of a derived class.

Property Injection:

class Base
{
    [Dependency]
    public IDep Dep { get; set; }
} 

Method Injection:

class Base
{
     private IDep dep;

     [InjectionMethod]
     public void Initialize(IDep dep)
     {
         this.dep = dep;
     }
}

Please note:

  • The object is instantiated (ctor injection) before method / property injection is performed
  • It might be adequate to adapt the design to not require a base class, see Composition over Inheritance
BatteryBackupUnit
  • 12,934
  • 1
  • 42
  • 68
6

This is how you should solve the problem:

class abstract Base : IBase
{
    private readonly IDep dep;

    protected Base(IDep dep)
    {
        if (dep == null) throw new ArgumentNullException("dep");
        this.dep = dep;
    }
}

Now your base class has just one constructor and this constructor defines all the dependencies the class requires. There's just one way to create this class and the class will protect its invariants. The dependency is places in a private field since other classes have no use in accessing this dependency.

With this base class, the derived class will look like this:

class Derived : Base
{
    private readonly IDep dep;

    public Derived(IDep dep) : base(dep)
    {
        this.dep = dep;
    }
}

Here the derived class also has one single constructor defining the dependencies this class requires. It can't be created in a different way. In case the class uses the dependency itself, it should store the dependency in a private field for later use. Also note that because this class has just one constructor, there is no ambiguity in what constructor to call and there is no reason to mark the constructor with a [InjectionConstructor] attribute.

Do note that I agree with BatteryBackupUnit. Since I apply Dependency Injection and the SOLID principles to my applications, I see little reason for using base classes any more. The use of Composition instead of inheritance often reduces the complexity of the system.

Steven
  • 166,672
  • 24
  • 332
  • 435
  • Yeah I can do like this. But my focus was not to use explicit Constructor call ( : base(dep)).And yes for multiple Constructor I do agree with you that i should avoid multiple Constructor. I do agree with BatteryBackupUnit that unity can not implicitly call the Injection Constructor as it is limitations of C#.net – Rajat Srivastava Sep 17 '14 at 06:19
  • 1
    I would declare `dep` as `protected readonly` in the base class. The `protected` modifier allows derived classes to access `dep`, while `readonly` prevents changes to it. This makes a duplication of the `dep` variable and its initialization in the derived class superfluous. – Olivier Jacot-Descombes Aug 04 '17 at 14:26
0

Simple and straight forward solution is to have an "InjectionMethod" in your Base class.

> public abstract class Base : IBase
>     {
> 
>         private IDep dep;
> 
>         [InjectionMethod]
>         public void Initialize(IDep dep)
>         {
>             if (dep == null) throw new ArgumentNullException("dep");
>             this.dep = dep;
> 
>             OnInitialize();
>         }
> 
>         public dep DepProperty
>         {
>             get
>             {
>                 return dep;
>             }
>         }
>         protected abstract void OnInitialize();
>     }

//now your Derived class Constructor will not be forced to have the IDep Parameter

class Derived : Base
{
    public Derived()
    {

    }

    protected override void OnInitialize()
    {
        // you can access the baseclass dependency Instance in this override
        object depObject = this.DepProperty;
    }
}