1

我需要在应用程序中启用后期绑定,并且我希望有一个选项来使用 JSON 配置文件显式配置服务。

我有一个接口IDependency和两个类DependencyOneDependencyTwo它们都实现了接口。我还有一个SomeService具有以下签名的构造函数的类:

public SomeService(IDependency dependency1, IDependency dependency2)

我想注入DependencyOnefordependency1DependencyTwofor dependency2

如何在不使用代码中的任何属性的情况下纯粹在 JSON 配置中进行配置?有可能吗?

需要无属性要求,因为后期绑定程序集不应该依赖于 AutoFac。

提前致谢。

更新:解决方案

Travis 在下面的回答包含指向常见问题解答的链接,这使我找到了可接受的解决方案。使用“标记”接口,例如IDependencyOne : IDependencyand IDependencyTwo : IDependency,然后SomeService(IDependencyOne dependency1, IDependencyTwo dependency2)。我不太喜欢的事情是,现在一个通用的装饰器IDependency需要实现所有标记,比如LoggingDecorator : IDependencyOne, IDependencyTwo我想在 中使用它SomeService,但只要标记保持为空,这不是一个大问题。这样我就不必在后期绑定的程序集中强制依赖 Autofac 的 dll,同时仍然在 JSON 文件中配置 DI。

4

1 回答 1

0

如果同一接口有两个不同的实现,不能被同等对待,那就是代码异味。有一个关于解决方法的常见问题解答,但简短的回答是,如果没有一些手动工作,您将无法像这样指定同一接口的两个不同实例。没有一种机制可以轻松地将其连接起来,因为这是一个设计问题。

花点时间阅读常见问题解答,了解原因以及如何解决此问题的其他想法,而不仅仅是我在这里展示的内容。

但是,让我们假设您无法更改界面IDependency,因为这通常是人们的症结所在。让我们还假设您不能出于……任何原因将其放入构造函数中DependencyOneDependencyTwo(这两个都是我首先要解决的问题,而不是试图使我的 DI 接线复杂化,但再说一次,为了争论,这不是一个选择。)

我可能会在配置中注册每个实例,并使用以后可以使用的元数据键。

{
  "components": [{
    "type": "MyAssembly.DependencyOne, MyAssembly",
    "services": [{
      "type": "MyAssembly.IDependency, MyAssembly"
    }],
    "metadata": [{
      "key": "type",
      "value": "One",
      "type": "System.String, mscorlib"
    }]
  }, {
    "type": "MyAssembly.DependencyTwo, MyAssembly",
    "services": [{
      "type": "MyAssembly.IDependency, MyAssembly"
    }],
    "metadata": [{
      "key": "type",
      "value": "Two",
      "type": "System.String, mscorlib"
    }]
  }]
}

好的,所以我们有两个组件,每个组件都公开相同的接口,每个组件都有一个元数据键Oneor Two

在您的课程中,您可以使用该元数据。

public class SomeService
{
  readonly IEnumerable<Meta<IDependency>> _dependencies;

  public SomeService(IEnumerable<Meta<IDependency>> dependencies)
  {
    _dependencies = dependencies;
  }

  public void DoSomething(string parameter)
  {
    var dep = _dependencies.First(a => a.Metadata["type"].Equals(parameter));
    dep.DoSomething();
  }
}

这个想法是您可以使用元数据选择合适的东西。显然要根据自己的需要进行调整;也许它不是来自调用者的参数,而是其他地方的代码中的某些东西;这个概念仍然成立。

不过,我再次强烈建议您查看常见问题解答强烈考虑重新设计以完全避免这种情况。从长远来看,这将使您和其他开发人员的生活更轻松。

于 2019-02-22T17:57:40.090 回答