autofac解析所有类型的开放泛型类型?

Sue*_*uno 9 c# autofac

我猜测没有办法像Autofac那样做以下内容,为ctor注入一个可枚举的开放泛型类型集合?各种Handle类型都有依赖关系,否则我只是动态构建它们.

    class EventOne : IEvent {...}
    class EventTwo : IEvent {...}
    class EventThree : IEvent {...}
    interface IHandleEvent<T> where T : IEvent {...}
    class HandleEventOne : IHandleEvent<EventOne> {...}
    class HandleEventTwo : IHandleEvent<EventTwo> {...}
    class HandleEventThree : IHandleEvent<EventThree> {...}

    builder.RegisterAssemblyTypes(myAssembies).AsClosedTypesOf(typeof(IHandleEvent<>));
    builder.RegisterType<AService>().As<IAService>();


    class AService : IAService
    {
      public AService(IEnumerable<IHandleEvent<IEvent>> handles)
      {...}
    }
Run Code Online (Sandbox Code Playgroud)

Ste*_*ven 9

正如评论中所解释的那样,你想要的东西是不可能在C#中实现的并且有充分的理由.如果你能够转换IHandleEvent<EventOne>IHandleEvent<IEvent>它,那么也允许EventTwo传入,这将在运行时失败.

所以你需要的是一个中介抽象,它允许获得所有兼容的事件处理程序并调用它们.这种调解员经常被调用IEventPublisher,可能看起来像这样:

public interface IEventPublisher {
    void Publish(IEvent e);
}
Run Code Online (Sandbox Code Playgroud)

您现在可以创建特定于容器的实现.例如,对于Autofac,这将如下所示:

public class AutofacEventPublisher : IEventPublisher {
    private readonly IComponentContext container;

    public AutofacBusinessRuleValidator(IComponentContext container) {
        this.container = container;
    }

    public void Publish(IEvent e) {
        foreach (dynamic handler in this.GetHandlers(e.GetType())) {
            handler.Handle((dynamic)e);
        }
    }

    private IEnumerable GetHandlers(Type eventType) =>
        (IEnumerable)this.container.Resolve(
            typeof(IEnumerable<>).MakeGenericType(
                typeof(IHandleEvent<>).MakeGenericType(eventType)));
}
Run Code Online (Sandbox Code Playgroud)

消费者现在可以依赖这种新的抽象:

class AService : IAService
{
    public AService(IEventPublisher publisher) {...}
}
Run Code Online (Sandbox Code Playgroud)