How to dependency inject repositories that inherit an abstract class (that inherits another abstract class) which implements the interface?
I will give you a simplified version of my current architecture.
Architecture (simplified):
public interface IConcreteRepository<TEntity, TId> where TEntity : class
{
// a lot of methods here, that are common for Repository Pattern
}
public abstract class BaseEntityFrameworkRepository<TEntity, TId> : IConcreteRepository<TEntity, TId> where TEntity : class
{
protected ApplicationDbContext Context { get; private set; }
protected DbSet<TEntity> Entities { get; private set; }
public BaseEntityFrameworkRepository(ApplicationDbContext context)
{
Context = context;
Entities = context.Set<TEntity>();
}
public abstract Task<TEntity> GetByIdAsync(TId id);
// a lot of implemented and abstract methods here
}
The most important class for my problem:
public abstract class BaseEntityRepository<TEntity, TId> : BaseEntityFrameworkRepository<TEntity, TId> where TEntity : BaseEntity<TId> where TId : struct
{
public BaseEntityRepository(ApplicationDbContext context) : base(context)
{
}
// this is the abstract class that I directly inherit when creating the repositories for each entity
}
Similar to the Base Entity Repository, but the ID is a composite key (ITuple constraint):
public abstract class BaseAssociativeEntityRepository<TEntity, TId> : BaseEntityFrameworkRepository<TEntity, TId> where TEntity : BaseAssociativeEntity where TId : ITuple
{
public BaseAssociativeEntityRepository(ApplicationDbContext context) : base(context)
{
}
// similar to the BaseEntityRepository, but uses a Tuple ID (composite key)
}
This is an example for a concrete repository in my architecture:
public class CurriculumVitaeRepository : BaseEntityRepository<CurriculumVitae, int>
{
public CurriculumVitaeRepository(ApplicationDbContext context) : base(context)
{
}
public sealed override async Task<CurriculumVitae> GetByIdAsync(int id)
{
// extra logic or different logic goes here
}
// this is where I put the extra classes that this concrete repository needs or override virtual methods from the base abstract class
}
This is my architecture. The problem is that in the current architecture I can't dependency inject the repository in a Service class with the IConcreteRepository interface, because it's lacking a lot of methods.
The question:
Are there any design patterns that could help me with the problem? Is replacing the BaseEntityFramework abstract class with 2 interfaces IEntityRepository and IAssociativeEntityRepository that will be implemented directly to BaseEntityRepository and BaseAssociativeEntityRepository the solution here? If I remove entirely BaseEntityFrameworkRepository, I will have to basically copy-paste a lot of logic into the other 2 classes (that are his children now).
IIdentityUserRepository
mentioned here? I don't see it being used anywhere. Or did I miss it?GetByIdAsync
method was originally defined. Based on your comments I would guess that this method is defined in theIConcreteRepository
or any of its ancestors, but your question seems to assert that that's not the case. A concrete example would really help in identifying the problem.