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

Support for scoped services being injected into schema types constructor #133

Open
ampersandd opened this issue Feb 28, 2019 · 7 comments
Open
Labels

Comments

@ampersandd
Copy link

For now it is possible to set own dependency injector for executor using WithDependencyInjector method. Then using InjectAttribute for parameters of Query methods we can inject scoped services using provided dependency container.
But what if we need to share scoped services within whole Query class injecting them into constructor?
For now services injected into constructor of schema type are resolved using typeResolutionDelegate provided into GraphQLEngine constructor. Engine mainly constructed one time and that's why there is no option to provide it with scoped services resolution (used in Microsoft ASP.NET Core dependency
container).
Is there any solution to use injector provided for executor by WithDependencyInjector method to resolve services for injection into constructor of schema types?

@tlil tlil added the question label Mar 12, 2019
@dmg-hamann
Copy link
Contributor

I guess it is not possible at the moment. The source is taken of the GraphQL.Dotnet infos this library gets. Maybe it would be possible to hand in an custom FieldResolver with some modifications.

The logic which that implementation would need to adjust is the method private object GetSource(GraphFieldInfo fieldInfo, IResolutionContext context) in FieldResolver. It could always trigger source = context.DependencyInjector?.Resolve(declaringType.GetTypeInfo()) ?? fieldInfo.SchemaInfo.TypeResolutionDelegate(declaringType);

To do this the engine would need some kind of method where you can handin the resolver or maybe even better a strategy for getting the source of a context or a fieldinfo.

@dmg-hamann
Copy link
Contributor

I guess it is even way easier and without any code change. The constructor of GraphQLEngine accepts a delegate for type resolution. Just add a delegate like (type) => IoCContainer.Resolve(type) .

It worked for me in a very small test. Maybe it solves your issue.

@BilyachenkoOY
Copy link
Contributor

@dmg-hamann, in you solution IoCContainer should be singleton/static instance, which do not allow usage of scoped (per request or manually created scopes) or child containers without hacks (e.g. marking with [ThreadStatic] which will not cover all use cases)

@dmg-hamann
Copy link
Contributor

Anything else which is resolved by the container can be scoped. I dont know how an asp service or prims currently works but at some point you register your dependencies at the container. Isn't the container always a singleton? Or where are the dependencies store?

@BilyachenkoOY
Copy link
Contributor

BilyachenkoOY commented Apr 30, 2019

Yes the container (dependencies storage) is singleton. But some services are scoped which means they will be created only inside scope (create manually or by ASP.NET per HTTP request) and they can be recreated inside another scope.

// this will not work
// var test = _serviceProvider.GetService<ISomeScopedService>();

var engine= new GraphQLEngine(_serviceProvider.GetService)
using (var scope = _serviceProvider.CreateScope())
{
    // e.g. here is how scoped service can be retrieved
    // var service = scope.ServiceProvider.GetService<ISomeScopedService>();

    var exec = engine.NewExecutor()
        // this allow to receive scoped service in Query methods but not in Query  ctor
        .WithDependencyInjector(new DependencyInjector(scope.ServiceProvider)) 
        .WithQueryString(query.Query);

    var result = await exec.Execute();
}

@BilyachenkoOY
Copy link
Contributor

Hmm... I was going to try to fix this. But I've just rechecked the issue and found that typeResolutionDelegate is not invoked when IDependencyInjector is specified for executor.

@sungam3r
Copy link
Member

Also see graphql-dotnet/graphql-dotnet#1151

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

No branches or pull requests

5 participants