Bind resolvers
Resolvers are used to resolve the data for the query, or execute mutations. They bind the execution of GraphQL operation into your logic.
See also
Bind using SchemaBuilder
When building the executable schema using Build
the SchemaBuilder
takes an IResolverMap
and/or ISubscriberMap
values. These
maps include the resolvers for fields of object types.
- Simplest form of a resolver is an delegate returning a value.
[Fact]
public async Task Part2_BindResolvers_ReturnValue()
{
// Create builder and load sdl
var builder = new SchemaBuilder()
.Add(@"
type Query {
name: String
}
");
// Build schema with the resolver
var schema = await builder.Build(new SchemaBuildOptions
{
Resolvers = new ResolversMap
{
{
"Query", "name", () => "Test"
}
}
});
// Quickest but least configurable way to execute
// queries against the schema is to use static
// execute method of the Executor
var result = await Executor.Execute(schema, @"{ name }");
result.ShouldMatchJson("""
{
"data": {
"name": "Test"
}
}
""");
}
- Use
ResolverContext
: context provides information about the query being executed.
[Fact]
public async Task Part2_BindResolvers_UseContext()
{
// Create builder and load sdl
var builder = new SchemaBuilder()
.Add(@"
type Query {
name: String
}
");
// Build schema with the resolver
var schema = await builder.Build(new SchemaBuildOptions
{
Resolvers = new ResolversMap
{
{
"Query", "name", (ResolverContext context) =>
{
context.ResolvedValue = "Test";
return default;
}
}
}
});
var result = await Executor.Execute(schema, @"{ name }");
result.ShouldMatchJson("""
{
"data": {
"name": "Test"
}
}
""");
}
- You can access properties of the
ResolverContext
by named parameters keeping the resolver simple. In this case we access the value of the parent calledobjectValue
.
[Fact]
public async Task Part2_BindResolvers_ObjectValue()
{
// Create builder and load sdl
var builder = new SchemaBuilder()
.Add("""
type Query {
vader: Parent
}
type Parent {
luke: String
}
""");
// Build schema with the resolvers
var schema = await builder.Build(new SchemaBuildOptions
{
Resolvers = new ResolversMap
{
{
"Query", "vader", () => "I am your father"
},
{
"Parent", "luke", (string objectValue) => $"Luke, {objectValue}"
}
}
});
var result = await Executor.Execute(schema, @"{ vader { luke }}");
result.ShouldMatchJson("""
{
"data": {
"vader": {
"luke": "Luke, I am your father"
}
}
}
""");
}
- For complex scenarios usage of
ResolversBuilder
is recommended
[Fact]
public async Task Part2_BindResolvers_ResolversBuilder()
{
// Create builder and load sdl
var builder = new SchemaBuilder()
.Add("""
type Query {
vader: Parent
}
type Parent {
luke: String
}
""");
// Build schema with the resolvers
var schema = await builder.Build(new SchemaBuildOptions
{
Resolvers = new ResolversBuilder()
.Resolvers("Query", new Dictionary<string, Action<ResolverBuilder>>()
{
["vader"] = b => b
// use middleware to modify the ResolvedValue
.Use(next => async context =>
{
await next(context);
context.ResolvedValue = $"------ {context.ResolvedValue}";
})
// this is the the actual resolver
.Run(() => "I am your father"),
})
.Resolvers("Parent", new Dictionary<string, Action<ResolverBuilder>>()
{
["luke"] = b => b.Run((string objectValue) => $"Luke, {objectValue}")
})
.BuildResolvers()
});
var result = await Executor.Execute(schema, @"{ vader { luke }}");
result.ShouldMatchJson("""
{
"data": {
"vader": {
"luke": "Luke, ------ I am your father"
}
}
}
""");
}