简体   繁体   中英

Cannot register nested generic interface in .NET Core

I am trying to register the nested generic type in DI container, but unable to register

throws {Open generic service type requires registering an open generic implementation type. (Parameter descriptors)} error

Implemented Interface method looks like:

public class CustomerEvent<TEntity> : IEventConsumer<EntityInsertedEvent<TEntity>>,
    IEventConsumer<EntityUpdatedEvent<TEntity>>,
    IEventConsumer<EntityDeletedEvent<TEntity>> where TEntity : BaseEntity
{
    public void HandleEvent(EntityInsertedEvent<TEntity> eventMessage)
    {
        throw new NotImplementedException("Inserted");
    }

    public void HandleEvent(EntityUpdatedEvent<TEntity> eventMessage)
    {
        throw new NotImplementedException("Updated");
    }

    public void HandleEvent(EntityDeletedEvent<TEntity> eventMessage)
    {
        throw new NotImplementedException("Deleted");
    }
}

Tried

Assembly.GetExecutingAssembly()
    .GetTypes()
    .Where(item => item.GetInterfaces()
    .Where(i => i.IsGenericType)
        .Any(i => i.GetGenericTypeDefinition() == typeof(IEventConsumer<>))
            && !item.IsAbstract && !item.IsInterface)
    .ToList().ForEach(assignedTypes =>
    {
        assignedTypes.GetInterfaces()
            .Where(i => i.GetGenericTypeDefinition() == typeof(IEventConsumer<>)).ToList()
            .ForEach(imp =>
            {
                services.AddScoped(imp, assignedTypes);
            });
    });

but failed

There is no easy way to do this. Typically, you need to map an open-generic abstraction to an open-generic implementation, like this:

services.AddTransient(typeof(IEventConsumer<>), typeof(CustomerEvent<>));

This, however, will not work in your case because MS.DI is unable to figure out how the generic type argument for IEventCustomer<T> should maps to the generic type argument of CustomerEvent<TEntity> . When resolving an IEventCustomer<EntityInsertedEvent<Order>> , for instance, it will try to create a CustomerEvent<EntityInsertedEvent<Order>> , while it should have been creating a CustomerEvent<Order> .

This is not a limitation of .NET or the CLR, but a limitation that is specific to the MS.DI DI Container, because some other DI Containers are actually able to make these kinds of mappings.

Unfortunately, with MS.DI, there is no easy way out. The only thing you can do is making all possible closed-generic registrations explicitly, eg:

s.AddTransient<IEventConsumer<EntityInsertedEvent<Order>>, CustomerEvent<Order>>();
s.AddTransient<IEventConsumer<EntityInsertedEvent<Customer>>, CustomerEvent<Customer>>();
s.AddTransient<IEventConsumer<EntityInsertedEvent<Product>>, CustomerEvent<Product>>();
s.AddTransient<IEventConsumer<EntityInsertedEvent<Employee>>, CustomerEvent<Employee>>();
s.AddTransient<IEventConsumer<EntityInsertedEvent<etc>>, CustomerEvent<etc>>();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM