【问题标题】:Indirect parameterized instantiation using Autofac使用 Autofac 的间接参数化实例化
【发布时间】:2017-01-24 23:16:34
【问题描述】:

我收到了一个 DependencyResolutionException 尝试使用 Autofac 的 parameterized instantiation 来解决 间接 依赖关系。

假设我有以下课程:

public interface IMuffin {}

public class Muffin : IMuffin
{
    public Muffin(IButter butter) {}
}

public interface IButter {}

public class Butter : IButter
{
    public Butter(IKnife knife) {}
}

public interface IKnife {}

现在假设我想要一个 IMuffin,但我想提供 IKnife 依赖项作为参数,如下所示:

public class Breakfast
{
    public Breakfast(Func<IKnife, IMuffin> muffinFactory)
    {
        var muffin = muffinFactory(new Knife());
    }

    private class Knife : IKnife {}
}

问题是,我在muffinFactory(new Knife()) 上遇到异常,抱怨工厂无法使用可用参数和服务解决Butter 构造函数的IKnife 依赖项。这是没有意义的,因为我提供了一个 IKnife 的实例作为工厂的参数。

这似乎应该有效。我错过了什么?

【问题讨论】:

  • 好的,我可以看到它们来自哪里,但是使用参数化实例化即使是 直接 依赖项也需要一些“知识”。只需一点点重构就可以将直接依赖关系转变为间接依赖关系。这实际上就是我的情况。使用上面的示例,假设Muffin 最初直接依赖于IKnife,那么Breakfast 的参数化实例化将起作用。当Butter 被分解时,IKnife 变成了一个间接依赖,它破坏了BreakfastIMuffin消费者不应该受到这种变化的影响。

标签: autofac


【解决方案1】:

您示例中的工厂是IMuffin 的工厂,您的IKnife 参数作为typed parameter 传递。但是,您的 Muffin 类不需要 IKnife 实例。它需要一个IButter 实例。

IKnife 实例是 Butter 类所必需的。但是您传递给工厂的参数只能用于创建Muffin 实例,而不能用于解析Muffin 的依赖关系。 muffinFactory 的正确类型是 Func&lt;IButter, IMuffin&gt;

要使您的示例工作,您需要两个工厂:

public class Breakfast
{
   public Breakfast(Func<IKnife, IButter> butterFactory, Func<IButter, IMuffin> muffinFactory)
   {
      var butter = butterFactory(new Knife());
      var muffin = muffinFactory(butter);
   }

   private class Knife : IKnife { }
}

【讨论】:

  • 是的,我在发布后尝试了这种方法。但是,由于 Autofac 可以遍历依赖关系树,它似乎应该能够携带您指定的参数来解决任何依赖关系,而不仅仅是顶级依赖关系。很失望,我必须手持它才能让IKnife 在第二级可用。
  • 故意不从顶层获取参数并将它们传递给整个堆栈的每个分辨率。 See the FAQ.
  • @TravisIllig,感谢您提供的链接——这很有帮助!不过,请参阅我对您对原始问题的评论的回复。
  • 看到了响应,并没有改变这是一个设计挑战的事实,并且一直向下传递解决方案堆栈没有意义。我相信这在 IoC 容器和一般模式中是相当标准的——你不应该知道整个解析链。
  • 我并不是说了解整个解析链中的所有依赖项是一个很棒的设计。但是 Autofac 显然支持了解 selected 一级依赖项(因此参数化实例化),并且还支持一种方便的重构技术,该技术导致一级依赖项变为二级依赖项(Extras.AggregateService),所以暗示通过同时使用这两个功能引入了一些重大的设计缺陷似乎有点强烈。
猜你喜欢
  • 2018-01-13
  • 2013-06-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-31
  • 1970-01-01
  • 2016-01-05
  • 1970-01-01
相关资源
最近更新 更多