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

Injecting scoped dependencies #126

Closed
braudabaugh opened this issue Feb 11, 2019 · 4 comments
Closed

Injecting scoped dependencies #126

braudabaugh opened this issue Feb 11, 2019 · 4 comments

Comments

@braudabaugh
Copy link
Contributor

Certain service objects, like database connections, need to have a lifetime of ServiceLifetime.Scoped so that sharing is limited to a single request. In order to allow these types of objects to be dependency injected, a new, scoped, dependency injector needs created for each request. Currently, the injector used to process GraphQL requests is specified when RequestHandler is constructed via the RequestHandlerBuilder.WithDependencyInjector method. This requires the RequestHandler to be re-constructed with each request in order to inject scoped objects. In order to avoid this overhead, I would like to propose adding an optional dependencyInjector parameter to the RequestHandler.ProcessRequest method that overrides the injector specified when the RequestHandler was constructed.

I have a PR ready that implements this and will link it to this issue for review.

@BilyachenkoOY
Copy link
Contributor

Hello.
Correct me, if I'm wrong, but there should be no difference how and when the dependency injector is constructed if it doesn't holds service instances. For example if you have default Core IServiceProvider, it doesn't mean that new scoped/transient services will not be created on the next GetService call.

@braudabaugh
Copy link
Contributor Author

braudabaugh commented Feb 11, 2019

The when is definitely different. In order to use scoped objects, the injector must also be resolved by a scope created at request time. The code below is basically what I'm using in my app's controller method that handles GraphQL requests. (note: _scopeFactory is an instance of IServiceScopeFactory)

           using (var scope = _scopeFactory.CreateScope())
           {
               var customInjector = scope.ServiceProvider.GetService<ICustomInjector>();
               using (var reader = new StreamReader(Request.Body))
               {
                    var query = await reader.ReadToEndAsync();
                    var request = GraphQLWeb.Request.New(query);

                    var result = await _schema.ProcessRequest(request, User, customInjector as IDependencyInjector);
                    return Content(result.Body, "application/json");
               }
           }

If you try to use an injector that is not scoped, created by the default provider, to inject a scoped service, you will get an exception similar to:

InvalidOperationException: Cannot resolve scoped service 'Blah.Blah+Blah' from root provider.

@BilyachenkoOY
Copy link
Contributor

You are right :)

@tlil
Copy link
Collaborator

tlil commented Feb 16, 2019

Thanks for the PR - merged. Closing this issue.

@tlil tlil closed this as completed Feb 16, 2019
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

3 participants