在构造函数注入期间解析为父接口

Resolving to parent interface during constructor injection

这里涉及到autofac和c#。我有一个从父接口派生的接口:

public interface IJ4JLogger<out TCalling>
{
}

public interface IJ4JSmsLogger<out TCalling> : IJ4JLogger<TCalling>
{
}

某些 classes 取决于在构造期间提供父接口的实例:

public FileHistoryConfiguration( IJ4JLogger<FileHistoryConfiguration> histLogger, IJ4JLogger<FileHistoryService> svcLogger )
{
}

但是如果我用 autofac 注册这样的类型:

builder.RegisterGeneric( typeof(J4JSmsLogger<>) )
    .As(typeof(IJ4JSmsLogger<>))
    .SingleInstance();

其中 J4JSmsLogger<> 是一个 class 实现 IJ4JSmsLogger<> 的地方,然后此调用失败并出现错误,即找不到任何已注册以提供 IJ4JLogger<> 接口的内容:

_fhConfig = _svcProvider.GetRequiredService<IFileHistoryConfiguration>();

我可以通过更改 J4JSmsLogger<> 注册中的 As<> 子句将其视为 IJ4JLogger<> 实例来解决该问题,然后每当我将解析该接口的结果转换为 IJ4JSmsLogger<>需要子界面的额外功能。

但我不明白为什么我必须这样做。在使用 autofac 注册类型的过程中,我是否需要采取额外的步骤,以便实现子接口的对象将满足对父接口的需求?

更清洁的解决方法

阅读有关 autofac 的更多信息,我学到了一些新东西:您可以根据需要定义任意数量的 As<>() 子句(包括 AsSelf())。因此,将我的 autofac 配置更改为:

builder.RegisterGeneric( typeof(J4JSmsLogger<>) )
    .As(typeof(IJ4JSmsLogger<>))
    .As(typeof(IJ4JLogger<>))
    .SingleInstance();

提供比不断投射已解析实例更简洁的解决方案。

不过,我不打算将其作为答案提交,因为我很好奇为什么 autofac 不自动执行这种向下转换,以及其他任何 DI 框架是否执行。

Autofac 不会像那样为您转换为基本类型。它通常假定接线是准确的。如果没有,你可以 运行 解决一些实际问题,比如如果有人有这样的构造函数......

public class BadTimes
{
  public BadTimes(object input) { }
}

里面放的是什么东西?一切都归结为对象。

但是,您始终可以将其注册为这两种类型并收工:

builder.RegisterGeneric(typeof(J4JSmsLogger<>))
    .As(typeof(IJ4JSmsLogger<>))
    .As(typeof(IJ4JLogger<>))
    .SingleInstance();