C# dependency injection multiple implementation of the same Generic Type

Viewed 184

Note : this is not a duplicate !

I have the following Example :

public interface IRepository<TEntity> where TEntity : IEntity
{
...

}

public class Repository<TEntity> : IRepository<TEntity> where TEntity : IEntity
{
...

}

public class Repository<SpecialClass> : IRepository<SpecialClass> 
{

...
}


public class SpecialClass: IEntity
{
...
}

Now I want to use Repository<> class for every IRepository<> except for IRepository<SpecialClass> :

// every IRepository<> :
services.AddScoped(typeof(IRepository<>), typeof(RepositoryEFCore<>));

// but not for SpecialClass
services.AddScoped(typeof(IRepository<SpecialClass>), typeof(Repository<SpecialClass>));

The question is how do I register two(or multiple) different classes for the same interface while the interface has already been registered for another class ?

1 Answers
services.AddScoped(typeof(IRepository<>), typeof(RepositoryEFCore<>));

This line will add all IRepository handler in DI container. To exclude some special class from DI registration, there is a way using reflection,

 Type[] handlers = Assembly.GetExecutingAssembly().GetTypes().Where(t => t.IsClass && t.Name != "SpecialClass" &&  t.GetInterfaces().
        Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IRepository<>))).ToArray();

        foreach (Type concreteHandler in handlers)
        {
            Type? handlerInterface = concreteHandler.GetInterfaces().First(i => i.GetGenericTypeDefinition() == typeof(IRepository<>));
            services.AddScoped(handlerInterface, concreteHandler);
        }

Here, handlers array will hold all concrete implementation of IRepository excluding Specialclass and using foreach you can add all objects with concrete implementation in DI.

Related