Autofac 不解析具有通用类型的服务

Autofac not resolving service with generic type

我有一个使用中介模式处理消息的 .NET Core 3.1 通用主机:

public interface IMessageDispatcher {
  Task Dispatch<TMessage>(TMessage message) where TMessage : Message;
}

public class MessageDispatcher : IMessageDispatcher {
  private readonly IServiceProvider _container;

  public MessageDispatcher(IServiceProvider container) {
    _container = container;
  }

  public async Task Dispatch<TMessage>(TMessage message) {
    var handler = (IMessageHandler<TMessage>) _container.GetService(typeof(IMessageHandler<TMessage>));
    await handler.Handle(message);
  }
}

public interface IMessageHandler<TMessage> where TMessage : Message {
  Task Handle(TMessage message);
}

public class MyMessageHandler : IMessageHandler<MyMessage> {
  public Task Handle(MyMessage message) {
    // do stuff
  }
}

消息处理器注册到Autofac,如下:

private static void AutoRegisterMessageHandlers(ContainerBuilder builder, Assembly domainAssembly) {
  builder
    .RegisterAssemblyTypes(domainAssembly)
    .AsClosedTypesOf(typeof(IMessageHandler<>));
}

如果我按原样 运行,那么当我调用 Handle 方法;但是,如果我在调用 Handle 和 运行 之前放置一个断点,则 Visual Studio 中的立即 window 中的以下内容:

_container.GetService(typeof(IMessageHandler<MyMessage>));

然后返回了预期的消息处理程序,这表明消息处理程序已正确注册,只是当我尝试使用通用类型解析消息处理程序时

_container.GetService(typeof(IMessageHandler<TMessage>));

事情出了问题。我做错了什么吗?

更新

根据接受的答案,我从消息队列接收消息并反序列化它们,所以我没有具体类型:

var message = Deserialiser.Deserialise<Message>(rawXmlFromQueue);
await Dispatch(message);

由于 message 没有具体类型,Autofac 没有足够的信息来定位已注册的消息处理程序,因此返回了 null。解决方案是将消息转换为 dynamic,通过 C# 类型系统的魔力,这足以将泛型类型转换为其具体实现:

var message = Deserialiser.Deserialise<Message>(rawXmlFromQueue);
await Dispatch((dynamic) message);

您无法解析开放式泛型。

你提到的问题是你不能这样做:

container.GetService(typeof(ICommandHandler<TMessage>))

但是 DI 并不神奇,它只是构建东西的另一种方式。你也不能这样做:

new CommandHandler<TMessage>()

也就是说,除非您知道 TMessage 是什么,否则这没有意义。你需要一个具体的类型。

然而,除此之外,很难弄清楚发生了什么。题少了很多

  • 它提到对 container. GetService 的调用返回 null 但不是您在返回 null 时要解决的问题。
  • 所有示例代码都显示 MessageHandler,但您在调试器中 运行 的示例是 CommandHandler。没有足够的信息知道这是错字还是问题的一部分。

无论如何,我希望能给你一些关于要看什么的想法。