Autofac的JSON配置中两个相同接口的实现

问题描述 投票:0回答:1

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

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

public SomeService(IDependency dependency1, IDependency dependency2)

我想为DependencyOne注入dependency1,为DependencyTwo注入dependency2

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

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

提前致谢。

更新:解决方案

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

autofac autofac-configuration
1个回答
0
投票

如果你有两个不同的同一个接口的实现,不能被对待,那就是代码味道。 There is an FAQ about ways to work around that,但简短的回答是你不会在没有一些手工工作的情况下直接指定相同界面的两个不同实例。没有一种机制可以轻松连接它,因为这是一个设计问题。

花一点时间阅读the FAQ,了解为什么以及如何解决这个问题的其他想法,而不仅仅是我在这里展示的内容。

但是,让我们假设您无法更改界面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"
    }]
  }]
}

好的,所以我们有两个组件,每个组件都公开相同的接口,每个组件的元数据键分别为OneTwo

In your class you can use that metadata.

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

我们的想法是您可以使用元数据选择合适的东西。显然适应你自己的需要;也许它不是来自调用者的参数,而是代码中的某些内容;这个概念仍然存在。

但是,我不能强烈推荐你check out the FAQ并强烈考虑重新设计以完全避免这种情况。从长远来看,它将使您的生活和开发伙伴的生活更轻松。

© www.soinside.com 2019 - 2024. All rights reserved.