I want to be able to resolve a collection of services from Autofac that represents all registered types which implement an open generic interface.
public interface IEntityService<in T> where T : Entity
{
void DoEntityWork(T entity);
}
I have many classes that inherit Entity
and many corresponding service classes which implement IEntityService
for that 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)
}
Here is how I am registering them with Autofac:
builder.RegisterType<EntityAService>().As<IEntityService<EntityA>();
builder.RegisterType<EntityBService>().As<IEntityService<EntityB>();
builder.RegisterType<EntityCService>().As<IEntityService<EntityC>();
What I would like to be able to do is to resolve each one of those IEntityService
registrations in a collection. However, attempting to inject them with the following code returns an empty collection:
public class MyProcessingClass(IEnumerable<IEntityService<Entity>> entityServices)
{
_entityServices = entityServices;
}
I have tried instead registering them all As<IEntityService<Entity>>()
, but this throws an ArgumentException
with the following message:
The type 'MyProject.Services.EntityAService' is not assignable to service 'MyProject.Interfaces.IEntityService'1[[MyProject.Models.Entity]]
How can I resolve all of the types which implement IEntityService
with a type argument that implements Entity
?
This is how contravariance works in C# works, EntityAService
is not IEntityService<Entity>
, this relation works another way around:
public class EntityService : IEntityService<Entity>
{
public void DoEntityWork(Entity entity) { }
}
IEntityService<EntityA> x = new EntityService();
One way around would be introducing a non-generic version of IEntityService
, registering all your entity services as that one and resolving IEnumerable<IEntityService>
.
Autofac doesn't support this sort of thing out of the box. There is a ContravariantRegistrationSource
but it does sort of the inverse of this - if you register IEntityService<Entity>
and then resolve IEntityService<EntityA>
it'll resolve the IEntityService<Entity>
instance for you. It doesn't allow you to resolve IEnumerable<IEntityService<Entity>>
and locate all the derived types.
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.