Update: Previous null error was because an empty constructor of Query
class with no parameters is created. Now I removed that empty constructor, but get a new Error: System.MissingMethodException: No parameterless constructor defined for type 'App.Controllers.Graphs.Query'
How can you inject your service into the GraphQL Query class? (Schema-first approach)
In my dotnet core 3.1 project, I have installed: GraphQL.Server.Transports.AspNetCore 3.5.0-alpha0046
Here is my root graph:
public class RootGraph : Schema
{
public RootGraph(IServiceProvider provider) : base(provider)
{
var schema = For(@"
type Player {
_id: ID!
dbname: String!
isPremium: Boolean!
games: [String]!
}
input PlayerView {
dbname: String!
isPremium: Boolean!
}
type Query {
player(dbname: String!): Player
}
", _ =>
{
_.Types.Include<Query>();
});
Console.WriteLine(provider); // <-- provider is not null here, everything is good
Query = schema.Query;
}
}
Then I create my Query class like this:
public class Query
{
private readonly ServiceProvider serviceProvider;
private readonly IPlayerService playerService;
public Query( IServiceProvider serviceProvider )
{
this.serviceProvider = serviceProvider as ServiceProvider;
this.playerService = serviceProvider.GetService<IPlayerService>();
}
[GraphQLMetadata("player")]
public async Task<Player> GetPlayer(string dbname)
{
Console.WriteLine(serviceProvider);
Player player = await playerService.Get(dbname);
return player;
}
}
But it's not working. The Query class cannot be created, because I get an exception here:
System.MissingMethodException: No parameterless constructor defined for type 'App.Controllers.Graphs.Query'.\r\n
at System.RuntimeType.CreateInstanceDefaultCtorSlow(Boolean publicOnly, Boolean wrapExceptions, Boolean fillCache)\r\n
at System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, Boolean wrapExceptions)\r\n
at System.Activator.CreateInstance(Type type, Boolean nonPublic, Boolean wrapExceptions)\r\n
at System.Activator.CreateInstance(Type type)\r\n
at GraphQL.DefaultServiceProvider.GetService(Type serviceType)\r\n
Part of my Startup.cs
:
public void ConfigureServices(IServiceCollection services){
...
// add services
services.AddSingleton<IPlayerService, PlayerService>();
// add GraphQL
services.AddSingleton<RootGraph>();
services.AddSingleton<Query>();
}
Anyone has an idea on how to provide services to Query class?
You have towrite this code in the startup class.
services.AddScoped<IServiceProvider , ServiceProvider >();
and declare the interface type in the class and pass to constructor.
private readonly IServiceProvider _serviceProvider ;
You can use AddSingleton
, AddTransient
or AddScoped
as per the requirement
So according to this thread , all I need to do is specify the service provider in the schema configuration, like this:
public RootGraph(IServiceProvider provider) : base(provider)
{
var schema = For(@"...", _ =>
{
_.Types.Include<Query>();
_.ServiceProvider = provider; // <=== Add this line here
});
// ...
}
You should be able to inject it directly without having to use the IServiceProvider. Something like this:
[GraphQLMetadata("Query")]
public class Query
{
private readonly IPlayerService playerService;
public Query(IPlayerService playerService)
{
this.playerService = playerService;
}
[GraphQLMetadata("player")]
public async Task<Player> GetPlayer(string dbname)
{
Console.WriteLine(serviceProvider);
Player player = await playerService.Get(dbname);
return player;
}
}
And then in your SchemaFile you have to add the ServiceProvider to your schema.
public class RootGraph : Schema
{
public RootGraph(IServiceProvider provider)
: base(provider)
{
var schema = For(@"
...
", _ =>
{
_.Types.Include<Query>();
_.ServiceProvider = provider;
});
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.