1

My goal is to create an object that contains different implementations of an interface and at runtime select the implementation to use. I'm using the Dependency injection in ASP.NET Core.

Code:

public interface IStateRepository : IDbReadRepository<IState> { }

public interface IDbReadRepository<T> : IBaseRepository
{
     IReadOnlyList<T> GetAll();
}

public interface IBaseRepository
{
    IUserContext UserContext { get; set; }
}

namespace MvcOpinionatedTemplate.Repositories.Dapper
{
    public class StateRepository : BaseDbRepository, IStateRepository
    {
        public StateRepository(IUserContext userContext, IDbConnection dbConnection) : base(userContext, dbConnection) { }

        public IReadOnlyList<IState> GetAll()
        {
            return _dbConnection.Query<State>("SELECT * FROM State").ToList();
        }
    }
}

namespace Template.Repositories.Local
{
    public class StateRepository : BaseRepository, IStateRepository
    {
        public StateRepository(IUserContext userContext) : base(userContext) { }

        public IReadOnlyList<IState> GetAll()
        {
            var filePath = Path.Combine(AppContext.BaseDirectory, @"Local\json\states.json");

            return JsonConvert.DeserializeObject<List<State>>(File.ReadAllText(filePath));
        }
}


namespace MvcOpinionatedTemplate.Repositories.Collections
{
    public class StateRepositories
    {
        public IStateRepository Local { get; }

        public IStateRepository SqlServer { get; }

        public StateRepositories(IStateRepository local, IStateRepository sqlServer)
        {
            Local = local;
            SqlServer = sqlServer;
        }
    }
}

What I'd like to do is set in the Startup.ConfigureServices():

services.AddTransient<StateRepositories, XXXXX>

I tried this:

services.AddTransient<StateRepositories>(s => new StateRepositories(new Repositories.Local.StateRepository(--UserContext--), new Repositories.Dapper.StateRepository(-UserContext--)));

The problem is how to have DI populate UserContext. I have it defined Startup.ConfigureServices():

services.AddScoped<IUserContext, UserContext>();

How do have DI populate UserContext for the StateRepositories implementations? Or is there a better approach to achieve my goal?

1

1 Answer 1

4

You can register your IStateRepository separately and then inject IEnumerable<IStateRepository> which injects all implementations of IStateRepository.

public interface IStateRepository
{
}

public class LocalRepository : IStateRepository
{
}

public class DapperRepository : IStateRepository
{
}

services.AddTransient<IStateRepository, LocalRepository>()
        .AddTransient<IStateRepository, DapperRepository>()
        .AddTransient<StateRepositories>();

public class StateRepositories
{
    public IStateRepository Local { get; }

    public IStateRepository SqlServer { get; }

    public StateRepositories(IEnumerable<IStateRepository> repositories)
    {
        Local = repositories.OfType<LocalRepository>().FirstOrDefault();
        SqlServer = repositories.OfType<DapperRepository>().FirstOrDefault();
    }
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.