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

时间:2016-04-05 19:27:42

标签: 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)
      {...}
    }

2 个答案:

答案 0 :(得分:9)

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

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

public interface IEventPublisher {
    void Publish(IEvent e);
}

您现在可以创建特定于容器的实现。例如,对于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)));
}

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

class AService : IAService
{
    public AService(IEventPublisher publisher) {...}
}

答案 1 :(得分:0)

您将无法将{ "name": "lib", "version": "0.0.1", "main": "lib.js", "typings": "lib" } 投射到IHandleEvent<EventThree>因为IHandleEvent<IEvent>不是协变,您可以通过添加IHandleEvent<T>修饰符来添加它。

out

不幸的是, Autofac 不支持协变类型,只支持逆变类型。 顺便说一下,您可以创建自定义public interface IHandleEvent<out TEvent> where TEvent : IEvent { } 实现以获得所请求的行为。像这样:

IRegistrationSource

使用此public class CovariantHandleEventRegistrationSource : IRegistrationSource { public bool IsAdapterForIndividualComponents { get { return false; } } public IEnumerable<IComponentRegistration> RegistrationsFor(Service service, Func<Service, IEnumerable<IComponentRegistration>> registrationAccessor) { IServiceWithType typedService = service as IServiceWithType; if (typedService == null) { yield break; } if (typedService.ServiceType.IsGenericType && typedService.ServiceType.GetGenericTypeDefinition() == typeof(IHandleEvent<>)) { IEnumerable<IComponentRegistration> eventRegistrations = registrationAccessor(new TypedService(typeof(IEvent))); foreach (IComponentRegistration eventRegistration in eventRegistrations) { Type handleEventType = typeof(IHandleEvent<>).MakeGenericType(eventRegistration.Activator.LimitType); IComponentRegistration handleEventRegistration = RegistrationBuilder.ForDelegate((c, p) => c.Resolve(handleEventType, p)) .As(service) .CreateRegistration(); yield return handleEventRegistration; } } } } ,您可以拥有:

IRegistrationSource