Need some help here please ...
I'm looking at the example "graphql-dotnet/server" where the exposed objects contains just plain properties. But what if I need to resolve a property and get data from a repository, how can I get hold of the respository class in the Type-class?
Example: The sample has a ChatQuery exposing "messages".
public ChatQuery(IChat chat)
{
Field<ListGraphType<MessageType>>("messages", resolve: context => chat.AllMessages.Take(100));
}
Instance "chat" is the repository here and is serving data (messages) via chat.AllMessages.
Let's say that a message has a list of viewers. Then I need to resolve that list from a repository. This is done in the other example "graphql-dotnet/examples" where the "StarWars/Types/StarWarsCharacter.cs" has a list of friends and the "StarWars/Types/HumanType" has the repository (StarWarsData) inserted in the constructor and can be used in the resolve method for "friends":
public class HumanType : ObjectGraphType<Human>
{
public HumanType(StarWarsData data)
{
Name = "Human";
Field(h => h.Id).Description("The id of the human.");
Field(h => h.Name, nullable: true).Description("The name of the human.");
Field<ListGraphType<CharacterInterface>>(
"friends",
resolve: context => data.GetFriends(context.Source)
);
Field<ListGraphType<EpisodeEnum>>("appearsIn", "Which movie they appear in.");
Field(h => h.HomePlanet, nullable: true).Description("The home planet of the human.");
Interface<CharacterInterface>();
}
}
BUT, doing the same thing in the server sample won't work.
public class MessageType : ObjectGraphType<Message>
{
public MessageType(IChat chat)
{
Field(o => o.Content);
Field(o => o.SentAt);
Field(o => o.From, false, typeof(MessageFromType)).Resolve(ResolveFrom);
Field<ListGraphType<Viewer>>(
"viewers",
resolve: context => chat.GetViewers(context.Source)
);
}
private MessageFrom ResolveFrom(ResolveFieldContext<Message> context)
{
var message = context.Source;
return message.From;
}
}
When I add the chat repository to the constructor in MessageType it fails.
I'm obviously missing something here; why isn't Dependency Injection injecting the chat instance into the MessageType class in the "graphql-dotnet/server" project? But it works in the "graphql-dotnet/examples" project.
Best, Magnus
To use DI you need to pass a dependency resolver in the constructor of your Schema class. The default resolver uses Activator.CreateInstance
, so you have to teach it about the Container you are using.
services.AddSingleton<IDependencyResolver>(
s => new FuncDependencyResolver(s.GetRequiredService));
IDependecyResolver
is an interface in the graphql-dotnet project.
public class StarWarsSchema : Schema
{
public StarWarsSchema(IDependencyResolver resolver)
: base(resolver)
{
Query = resolver.Resolve<StarWarsQuery>();
Mutation = resolver.Resolve<StarWarsMutation>();
}
}