Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Retrieve instance from scope #549

Closed
ArnaudB88 opened this issue Nov 3, 2020 · 4 comments
Closed

Retrieve instance from scope #549

ArnaudB88 opened this issue Nov 3, 2020 · 4 comments

Comments

@ArnaudB88
Copy link

ArnaudB88 commented Nov 3, 2020

Hi,

We have a solution where most of the container resolves happen through constructor injection.
But for some resolves, we have code like this:

public class UnitOfWork : IUnitOfWork
{
        public IGenericRepository<T> RepositoryFor<T>(bool ignoreSoftDeleteFilter = false) where T : class, IEntityBase, new()
        {
            var container = ContainerManager.Container.GetInstance<IGenericRepository<T>>();
            container.IgnoreQueryFilters = ignoreSoftDeleteFilter;
            return container;
        }
}

As you can see, at runtime we need instances resolved from the container based on a Type. Therefor we hold a static reference to the container (ContainerManager.Container) and request an instance with GetInstance(). But that static reference to the container is not the scope.
When making an api call, this specific code (needed for db access) throws an error because the IGenericRepository implementation has the dbContext (scoped) in the constructor. Since the code is requesting an instance of IGenericRepository from the root container, no scope exists.

My question:
Is there a way to retrieve the current scope which we can inject in the constructor? I already tried to add 'Scope scope' as a constructor parameter, hoping it would be resolved but it throws an exception.
If that would be possible, the above code could be rewritten to:

public class UnitOfWork : IUnitOfWork
{
        private readonly IScope CurrentScope;
        public UnitOfWork(IScope scope)
        {
            CurrentScope = scope;
        }
        public IGenericRepository<T> RepositoryFor<T>(bool ignoreSoftDeleteFilter = false) where T : class, IEntityBase, new()
        {
            var container = CurrentScope.GetInstance<IGenericRepository<T>>();
            container.IgnoreQueryFilters = ignoreSoftDeleteFilter;
            return container;
        }

I know this is possible with Unity. The acting container (~scope) registers itself so it can be contructor injected.
Can you help me with this problem?

Thanks!

@seesharper
Copy link
Owner

Could you create a simple repro, preferably something like a console app that I can run ?

@ArnaudB88
Copy link
Author

@seesharper You can reproduce this issue with an example solution:
https://github.com/ArnaudB88/LightInject_ArnaudB88

@ArnaudB88
Copy link
Author

@seesharper I added a second example, more complex than the first one.
Thank you for looking into this!

@ArnaudB88
Copy link
Author

For possible other developers, seesharper proposed the following solution:
Indeed injecting the serviceFactory in the constructor like:

public class UnitOfWork : IUnitOfWork
{
	private readonly IServiceFactory _serviceFactory;
	public UnitOfWork(IServiceFactory serviceFactory)
	{
		_serviceFactory = serviceFactory;
	}

	public IGenericRepository<T> RepositoryFor<T>(bool ignoreSoftDeleteFilter = false) where T : class, IEntityBase, new()
	{
		var repo = _serviceFactory.GetInstance<IGenericRepository<T>>();
		return repo;
	}
}

But in combination with registering the class above also as scoped and passing the serviceFactory explicitly in the compositionRoot:

registry.RegisterScoped<IUnitOfWork>(factory => new UnitOfWork(factory));

This is needed because the container can't resolve it own interface (the exception I mentioned in the original post).

@seesharper Thank you again for the (very fast) help you provided!
This issue can be closed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants