问题描述:

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??

网友答案:

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
网友答案:

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.

网友答案:

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;
    }
}
相关阅读:
Top