隐式地在Base类中注入依赖,而派生类通过Unity解析

时间:2014-09-11 05:30:40

标签: c# dependency-injection unity-container constructor-injection

我有一个基类Class Base,它具有dependecy Dep和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;            
    }
}

我认为在解析派生类时,应该自动注入Dependency dep(通过Constructor Injection)。

但是当我从它派生一个类并解析该类时,这似乎不起作用,而是调用Base的默认构造函数。

当我从Derived Class中显式调用构造函数时,我才能使它工作。

class Derived : Base
{

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

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

unity是否提供了任何直接的方法来隐式调用基类的注入构造函数(而不是通过显式的Construtor调用)? 如果没有,是否有任何理由说明为什么统一容器本身没有做到?

3 个答案:

答案 0 :(得分:16)

不,团结是无法做到的。实际上,没有一个容器可以这样做。 构造函数用于实例化一个类。如果你调用两个构造函数,最终会得到两个实例。如果基类是抽象的,你甚至无法调用它的构造函数(除了你知道的派生构造函数)。

因此,通过C#.net的限制,如果要使用构造函数注入,只有在将值显式注入调用非默认Derived构造函数的Base构造函数时,它才会起作用。

但是,您可以选择使用Property或Method注入。使用这些,您不必将依赖项添加到派生类的每个构造函数。

<强> 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;
     }
}

请注意:

  • 在执行方法/属性注入之前实例化对象(ctor注入)
  • 将设计调整为不需要基类可能就足够了,请参阅Composition over Inheritance

答案 1 :(得分:5)

这就是解决问题的方法:

class abstract Base : IBase
{
    private readonly IDep dep;

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

现在你的基类只有一个构造函数,这个构造函数定义了类所需的所有依赖项。只有一种方法可以创建这个类,该类将保护其不变量。依赖项位于私有字段中,因为其他类在访问此依赖项时没有用处。

使用此基类,派生类将如下所示:

class Derived : Base
{
    private readonly IDep dep;

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

此处派生类还有一个构造函数,用于定义此类所需的依赖项。它不能以不同的方式创建。如果类使用依赖项本身,它应该将依赖项存储在私有字段中供以后使用。另请注意,因为此类只有一个构造函数,所以要调用的构造函数没有歧义,并且没有理由使用[InjectionConstructor]属性标记构造函数。

请注意我同意BatteryBackupUnit。由于我将依赖注入和SOLID原则应用于我的应用程序,因此我认为没有理由再使用基类了。使用Composition而不是继承通常会降低系统的复杂性。

答案 2 :(得分:0)

简单直接的解决方案是拥有一个&#34; InjectionMethod&#34;在您的基础课程中。

> 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();
>     }

//现在你的Derived类构造函数不会被强制拥有IDep参数

class Derived : Base
{
    public Derived()
    {

    }

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