Разрешить IEnumerable всех типов, которые реализуют интерфейс Generi c в Autofac - PullRequest
0 голосов
/ 06 августа 2020

Я хочу иметь возможность разрешить набор служб из Autofa c, который представляет все зарегистрированные типы, реализующие открытый интерфейс generi c.

public interface IEntityService<in T> where T : Entity
{
    void DoEntityWork(T entity);
}

У меня много классов, наследующих Entity и многие соответствующие классы обслуживания, которые реализуют IEntityService для этой Entity.

public class EntityA : Entity { }
public class EntityB : Entity { }
public class EntityC : Entity { }

public class EntityAService : IEntityService<EntityA>
{
    public void DoEntityWork(EntityA entity)
}

public class EntityBService : IEntityService<EntityB>
{
    public void DoEntityWork(EntityB entity)
}

public class EntityCService : IEntityService<EntityC>
{
    public void DoEntityWork(EntityB entity)
}

Вот как я регистрирую их в Autofa c:

builder.RegisterType<EntityAService>().As<IEntityService<EntityA>();
builder.RegisterType<EntityBService>().As<IEntityService<EntityB>();
builder.RegisterType<EntityCService>().As<IEntityService<EntityC>();

Что бы я хотелось бы иметь возможность разрешить каждую из этих IEntityService регистраций в коллекции. Однако попытка ввести их с помощью следующего кода возвращает пустую коллекцию:

public class MyProcessingClass(IEnumerable<IEntityService<Entity>> entityServices)
{
    _entityServices = entityServices;
}

Вместо этого я попытался зарегистрировать их все As<IEntityService<Entity>>(), но это вызывает ArgumentException со следующим сообщением:

The type 'MyProject.Services.EntityAService' is not assignable to service 'MyProject.Interfaces.IEntityService'1[[MyProject.Models.Entity]]

Как я могу разрешить все типы, реализующие IEntityService, с аргументом типа, реализующим Entity?

Ответы [ 2 ]

2 голосов
/ 06 августа 2020

Вот как контравариантность работает в C# работает, EntityAService не IEntityService<Entity>, это отношение работает по-другому:

public class EntityService : IEntityService<Entity>
{
    public void DoEntityWork(Entity entity) { }
}

IEntityService<EntityA> x = new EntityService();

В одном направлении было бы введение необщей c версии IEntityService, регистрация всех сервисов вашей сущности как эта и разрешение IEnumerable<IEntityService>.

1 голос
/ 07 августа 2020

Autofa c не поддерживает подобные вещи из коробки. Существует ContravariantRegistrationSource, но он вроде как обратный этому - если вы зарегистрируете IEntityService<Entity>, а затем разрешите IEntityService<EntityA>, он разрешит экземпляр IEntityService<Entity> за вас. Это не позволяет вам разрешить IEnumerable<IEntityService<Entity>> и найти все производные типы.

...