1

I'm using UnitOfWork in my asp.net 5 project as shown below:

public class UnitOfWork : IUnitOfWork
{
    private readonly BaseContext _context;
    private IAsyncRepository<CategoryEntity> _categoryRepository;
    private IAsyncRepository<ItemEntity> _itemRepository;

    public UnitOfWork(BaseContext context)
    {
        _context = context;
    }

    public IAsyncRepository<CategoryEntity> CategoryRepository
    {
        get
        {
            return _categoryRepository ??= new CategoryRepository(_context);
        }
    }

    public IAsyncRepository<ItemEntity> ItemRepository
    {
        get
        {
            return _itemRepository ??= new ItemRepository(_context);
        }
    }
}

Is there any way to lazy inject my CategoryRepository : IAsyncRepository or ItemRepository : IAsyncRepository using dependency injection in such a way that it will only be instantiated only when I'm accessing the particular repository and also same DbContext needs to be shared between Repositories? This could help to remove the tight coupling. Please assist.

fingers10
  • 6,675
  • 10
  • 49
  • 87
  • 1
    This design has its challenges. The dependency should be the other way around. The repositories would need to depend on the unit of work otherwise a factory abstraction would be needed which could complicate the design even further. – Nkosi Aug 22 '21 at 11:40
  • [this](https://stackoverflow.com/a/16085891/1515209) approach works regardless of the container you use – qujck Aug 22 '21 at 18:23

1 Answers1

1

Try to use IServiceProvider for such task.

public class UnitOfWork : IUnitOfWork
{
    private readonly BaseContext _context;
    private readonly IServiceProvider _provider;
    private IAsyncRepository<CategoryEntity> _categoryRepository;
    private IAsyncRepository<ItemEntity> _itemRepository;

    public UnitOfWork(BaseContext context, IServiceProvider provider)
    {
        _context = context;
        _provider = provider;
    }

    private T InitService<T>(ref T member)
    {
        return member ??= _provider.GetService<T>();
    }

    public IAsyncRepository<CategoryEntity> CategoryRepository
    {
        get
        {
            return InitService(ref _categoryRepository);
        }
    }

    public IAsyncRepository<ItemEntity> ItemRepository
    {
        get
        {
            return InitService(ref _itemRepository);
        }
    }
}
Svyatoslav Danyliv
  • 21,911
  • 3
  • 16
  • 32
  • what about `_context`? will it be shared between repositories? – fingers10 Aug 22 '21 at 11:45
  • 1
    If context registered as Scoped, yes. – Svyatoslav Danyliv Aug 22 '21 at 11:47
  • what about this lazy implementation in this [link](https://stackoverflow.com/questions/44934511/does-net-core-dependency-injection-support-lazyt) ? is it a good approach? – fingers10 Aug 22 '21 at 11:50
  • Also interesting approach. But thread safety is overkill here. – Svyatoslav Danyliv Aug 22 '21 at 11:58
  • This unit of work has now become a repository factory. I know OP example is most likely minimal but if context is not explicitly being used with the unit then it can be removed since it will be injected into the repositories when being resolved. – Nkosi Aug 22 '21 at 13:09
  • @Svyatoslav Danyliv for some reason the answer that you have shared makes the application slower. This solution is thread safe? – fingers10 Aug 22 '21 at 18:41