我希望能够从Autofac解析一个服务集合,该集合表示实现开放通用接口的所有注册类型。
public interface IEntityService<in T> where T : Entity
{
void DoEntityWork(T entity);
}
我有许多继承Entity
的类,以及许多为该实体实现IEntityService
的相应服务类。
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)
}
以下是我如何在Autofac:注册它们
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]]
如何使用实现Entity
的类型参数解析实现IEntityService
的所有类型?
Autofac不支持这种开箱即用的东西。有一个ContravariantRegistrationSource
,但它确实与此相反——如果您注册IEntityService<Entity>
,然后解析IEntityService<EntityA>
,它将为您解析IEntityService<Entity>
实例。它不允许您解析IEnumerable<IEntityService<Entity>>
并定位所有派生类型。
这就是C#中反方差的工作方式,EntityAService
不是IEntityService<Entity>
,这种关系以另一种方式工作:
public class EntityService : IEntityService<Entity>
{
public void DoEntityWork(Entity entity) { }
}
IEntityService<EntityA> x = new EntityService();
一种方法是引入IEntityService
的非通用版本,将所有实体服务注册为该版本并解析IEnumerable<IEntityService>
。