public ExecutionContext BuildExecutionContext( Schema schema, object root, Document document, string operationName, Inputs inputs) { var context = new ExecutionContext(); context.Schema = schema; context.RootObject = root; var operation = !string.IsNullOrWhiteSpace(operationName) ? document.Operations.WithName(operationName) : document.Operations.FirstOrDefault(); if (operation == null) { context.Errors.Add(new ExecutionError("Unknown operation name: {0}".ToFormat(operationName))); return context; } context.Operation = operation; context.Variables = GetVariableValues(schema, operation.Variables, inputs); context.Fragments = document.Fragments; return context; }
public Task <object> ExecuteOperation(ExecutionContext context) { var rootType = GetOperationRootType(context.Schema, context.Operation); var fields = CollectFields( context, rootType, context.Operation.Selections, new Dictionary <string, Fields>(), new List <string>()); return(ExecuteFields(context, rootType, context.RootValue, fields)); }
public Task <Dictionary <string, object> > ExecuteOperationAsync(ExecutionContext context) { var rootType = GetOperationRootType(context.Document, context.Schema, context.Operation); var fields = CollectFields( context, rootType, context.Operation.SelectionSet, new Dictionary <string, Field>(), new List <string>()); return(ExecuteFieldsAsync(context, rootType, context.RootValue, fields, new string[0])); }
private IDictionary <string, Field> SubFieldsFor(ExecutionContext context, IGraphType fieldType, Field field) { if (!(fieldType is IObjectGraphType) || !field.SelectionSet.Selections.Any()) { return(null); } var subFields = new Dictionary <string, Field>(); var visitedFragments = new List <string>(); var fields = CollectFields(context, fieldType, field.SelectionSet, subFields, visitedFragments); return(fields); }
private ResolveFieldResult <object> GenerateError( ResolveFieldResult <object> resolveResult, Field field, ExecutionContext context, Exception exc, IEnumerable <string> path) { var error = new ExecutionError("Error trying to resolve {0}.".ToFormat(field.Name), exc); error.AddLocation(field, context.Document); error.Path = path; context.Errors.Add(error); resolveResult.Skip = false; return(resolveResult); }
public async Task <IDictionary <string, object> > ExecuteFieldsAsync(ExecutionContext context, IObjectGraphType rootType, object source, Dictionary <string, Field> fields, IEnumerable <string> path) { var data = new ConcurrentDictionary <string, object>(); var externalTasks = new List <Task>(); foreach (var fieldCollection in fields) { var currentPath = path.Concat(new[] { fieldCollection.Key }); var field = fieldCollection.Value; var fieldType = GetFieldDefinition(context.Document, context.Schema, rootType, field); if (fieldType?.Resolver == null || !fieldType.Resolver.RunThreaded() || context.Operation.OperationType == OperationType.Mutation || fields.Count == 1) { await ExtractFieldAsync(context, rootType, source, field, fieldType, data, currentPath) .ConfigureAwait(false); } else { var task = Task.Run(() => ExtractFieldAsync(context, rootType, source, field, fieldType, data, currentPath), context.CancellationToken); externalTasks.Add(task); } } if (externalTasks.Count > 0) { await Task.WhenAll(externalTasks) .ConfigureAwait(false); } var ordered = new Dictionary <string, object>(); foreach (var fieldCollection in fields) { var name = fieldCollection.Key; if (!data.ContainsKey(name)) { continue; } ordered.Add(name, data[name]); } return(ordered); }
protected override IExecutionStrategy SelectExecutionStrategy(ExecutionContext context) { switch (context.Operation.OperationType) { case OperationType.Query: return(new ParallelExecutionWithAuthorizationStrategy()); case OperationType.Mutation: return(new SerialExecutionWithAuthorizationStrategy()); case OperationType.Subscription: return(new SubscriptionExecutionStrategy()); default: throw new InvalidOperationException($"Unexpected OperationType {context.Operation.OperationType}"); } }
protected virtual IExecutionStrategy SelectExecutionStrategy(ExecutionContext context) { // TODO: Should we use cached instances of the default execution strategies? switch (context.Operation.OperationType) { case OperationType.Query: return(new ParallelExecutionStrategy()); case OperationType.Mutation: return(new SerialExecutionStrategy()); case OperationType.Subscription: return(new SubscriptionExecutionStrategy()); default: throw new InvalidOperationException($"Unexpected OperationType {context.Operation.OperationType}"); } }
/// <summary> /// Resolve simple fields in a performant manor /// </summary> private static async Task <object> ResolveFieldFromDataAsync(ExecutionContext context, IObjectGraphType rootType, object source, FieldType fieldType, Field field, IEnumerable <string> path) { object result = null; try { if (fieldType.Resolver != null) { var rfc = new ResolveFieldContext(context, field, fieldType, source, rootType, null, path); result = fieldType.Resolver.Resolve(rfc); result = await UnwrapResultAsync(result) .ConfigureAwait(false); } else { result = NameFieldResolver.Resolve(source, field.Name); } if (result != null) { var scalarType = fieldType.ResolvedType as ScalarGraphType; result = scalarType?.Serialize(result); } } catch (Exception exc) { var error = new ExecutionError($"Error trying to resolve {field.Name}.", exc); error.AddLocation(field, context.Document); error.Path = path.ToList(); context.Errors.Add(error); // If there was an exception, the value of result cannot be trusted result = null; } return(result); }
/// <summary> /// Resolve lists in a performant manor /// </summary> private async Task <List <object> > ResolveListFromData(ExecutionContext context, object source, IObjectGraphType parentType, IGraphType graphType, Field field, IEnumerable <string> path) { var result = new List <object>(); var listInfo = graphType as ListGraphType; var subType = listInfo?.ResolvedType as IObjectGraphType; var data = source as IEnumerable; var visitedFragments = new List <string>(); var subFields = CollectFields(context, subType, field.SelectionSet, null, visitedFragments); if (data == null) { var error = new ExecutionError("User error: expected an IEnumerable list though did not find one."); error.AddLocation(field, context.Document); throw error; } var index = 0; foreach (var node in data) { var currentPath = path.Concat(new[] { $"{index++}" }); if (subType != null) { var nodeResult = await ExecuteFieldsAsync(context, subType, node, subFields, currentPath) .ConfigureAwait(false); result.Add(nodeResult); } else { var nodeResult = await CompleteValueAsync(context, parentType, listInfo?.ResolvedType, field, node, currentPath) .ConfigureAwait(false); result.Add(nodeResult); } } return(result); }
public bool ShouldIncludeNode(ExecutionContext context, Directives directives) { if (directives != null) { var directive = directives.Find(DirectiveGraphType.Skip.Name); if (directive != null) { var values = GetArgumentValues( context.Schema, DirectiveGraphType.Skip.Arguments, directive.Arguments, context.Variables); object ifObj; values.TryGetValue("if", out ifObj); bool ifVal; return(!(bool.TryParse(ifObj?.ToString() ?? string.Empty, out ifVal) && ifVal)); } directive = directives.Find(DirectiveGraphType.Include.Name); if (directive != null) { var values = GetArgumentValues( context.Schema, DirectiveGraphType.Include.Arguments, directive.Arguments, context.Variables); object ifObj; values.TryGetValue("if", out ifObj); bool ifVal; return(bool.TryParse(ifObj?.ToString() ?? string.Empty, out ifVal) && ifVal); } } return(true); }
public bool DoesFragmentConditionMatch(ExecutionContext context, IHaveFragmentType fragment, GraphType type) { var conditionalType = context.Schema.FindType(fragment.Type); if (conditionalType == type) { return(true); } if (conditionalType is InterfaceGraphType) { var interfaceType = (InterfaceGraphType)conditionalType; var hasInterfaces = type as IImplementInterfaces; if (hasInterfaces != null) { var interfaces = context.Schema.FindTypes(hasInterfaces.Interfaces); return(interfaceType.IsPossibleType(interfaces)); } } return(false); }
private ExecutionContext BuildExecutionContext( ISchema schema, object root, Document document, Operation operation, Inputs inputs, IDictionary <string, object> userContext, CancellationToken cancellationToken, Metrics metrics, List <IDocumentExecutionListener> listeners, bool throwOnUnhandledException, Action <UnhandledExceptionContext> unhandledExceptionDelegate, int?maxParallelExecutionCount, IServiceProvider requestServices) { var context = new ExecutionContext { Document = document, Schema = schema, RootValue = root, UserContext = userContext, Operation = operation, Variables = inputs == null ? null : GetVariableValues(document, schema, operation?.Variables, inputs), Fragments = document.Fragments, Errors = new ExecutionErrors(), Extensions = new Dictionary <string, object>(), CancellationToken = cancellationToken, Metrics = metrics, Listeners = listeners, ThrowOnUnhandledException = throwOnUnhandledException, UnhandledExceptionDelegate = unhandledExceptionDelegate, MaxParallelExecutionCount = maxParallelExecutionCount, RequestServices = requestServices }; return(context); }
private async Task ExtractFieldAsync(ExecutionContext context, IObjectGraphType rootType, object source, Field field, FieldType fieldType, ConcurrentDictionary <string, object> data, IEnumerable <string> path) { context.CancellationToken.ThrowIfCancellationRequested(); var name = field.Alias ?? field.Name; if (data.ContainsKey(name)) { return; } if (!ShouldIncludeNode(context, field.Directives)) { return; } if (CanResolveFromData(field, fieldType)) { var result = await ResolveFieldFromDataAsync(context, rootType, source, fieldType, field, path) .ConfigureAwait(false); data.TryAdd(name, result); } else { var result = await ResolveFieldAsync(context, rootType, source, field, path) .ConfigureAwait(false); if (result.Skip) { return; } data.TryAdd(name, result.Value); } }
public async Task <object> CompleteValueAsync(ExecutionContext context, IGraphType fieldType, Fields fields, object result) { var field = fields != null?fields.FirstOrDefault() : null; var fieldName = field != null ? field.Name : null; var nonNullType = fieldType as NonNullGraphType; if (nonNullType != null) { var type = nonNullType.ResolvedType; var completed = await CompleteValueAsync(context, type, fields, result).ConfigureAwait(false); if (completed == null) { var error = new ExecutionError("Cannot return null for non-null type. Field: {0}, Type: {1}!." .ToFormat(fieldName, type.Name)); error.AddLocation(field, context.Document); throw error; } return(completed); } if (result == null) { return(null); } if (fieldType is ScalarGraphType) { var scalarType = fieldType as ScalarGraphType; var coercedValue = scalarType.Serialize(result); return(coercedValue); } if (fieldType is ListGraphType) { var list = result as IEnumerable; if (list == null) { var error = new ExecutionError("User error: expected an IEnumerable list though did not find one."); error.AddLocation(field, context.Document); throw error; } var listType = fieldType as ListGraphType; var itemType = listType.ResolvedType; var results = await list.MapAsync(async item => await CompleteValueAsync(context, itemType, fields, item).ConfigureAwait(false)).ConfigureAwait(false); return(results); } var objectType = fieldType as IObjectGraphType; if (fieldType is IAbstractGraphType) { var abstractType = fieldType as IAbstractGraphType; objectType = abstractType.GetObjectType(result); if (objectType != null && !abstractType.IsPossibleType(objectType)) { var error = new ExecutionError( "Runtime Object type \"{0}\" is not a possible type for \"{1}\"" .ToFormat(objectType, abstractType)); error.AddLocation(field, context.Document); throw error; } } if (objectType == null) { return(null); } if (objectType.IsTypeOf != null && !objectType.IsTypeOf(result)) { var error = new ExecutionError( "Expected value of type \"{0}\" but got: {1}." .ToFormat(objectType, result)); error.AddLocation(field, context.Document); throw error; } var subFields = new Dictionary <string, Fields>(); var visitedFragments = new List <string>(); fields.Apply(f => { subFields = CollectFields(context, objectType, f.SelectionSet, subFields, visitedFragments); }); return(await ExecuteFieldsAsync(context, objectType, result, subFields).ConfigureAwait(false)); }
public async Task <object> ExecuteFields(ExecutionContext context, ObjectGraphType rootType, object source, Dictionary <string, Fields> fields) { return(await fields.ToDictionaryAsync( pair => pair.Key, pair => ResolveField(context, rootType, source, pair.Value))); }
public bool DoesFragmentConditionMatch(ExecutionContext context, IHaveFragmentType fragment, GraphType type) { var conditionalType = context.Schema.FindType(fragment.Type); if (conditionalType == type) { return true; } if (conditionalType is InterfaceGraphType) { return ((InterfaceGraphType)conditionalType).IsPossibleType(type as IImplementInterfaces); } return false; }
/// <summary> /// Processes data from the source stream via <see cref="IObserver{T}.OnNext(T)"/> and /// returns an <see cref="ExecutionResult"/>. /// <br/><br/> /// Executes with a scoped service provider in <see cref="ExecutionContext.RequestServices"/> /// which is disposed once this method completes. /// </summary> protected override async ValueTask <ExecutionResult> ProcessDataAsync(ExecutionContext context, ExecutionNode node, object?value) { using var scope = _serviceScopeFactory.CreateScope(); context.RequestServices = scope.ServiceProvider; return(await base.ProcessDataAsync(context, node, value).ConfigureAwait(false)); }
private ResolveFieldResult<object> GenerateError(ResolveFieldResult<object> resolveResult, Field field, ExecutionContext context, Exception exc) { var error = new ExecutionError("Error trying to resolve {0}.".ToFormat(field.Name), exc); error.AddLocation(field, context.Document); context.Errors.Add(error); resolveResult.Skip = false; return resolveResult; }
public async Task <ResolveFieldResult <object> > ResolveFieldAsync(ExecutionContext context, IObjectGraphType parentType, object source, Field field, IEnumerable <string> path) { context.CancellationToken.ThrowIfCancellationRequested(); var fieldPath = path?.ToList() ?? new List <string>(); var resolveResult = new ResolveFieldResult <object> { Skip = false }; var fieldDefinition = GetFieldDefinition(context.Document, context.Schema, parentType, field); if (fieldDefinition == null) { resolveResult.Skip = true; return(resolveResult); } var arguments = GetArgumentValues(context.Schema, fieldDefinition.Arguments, field.Arguments, context.Variables); try { var resolveContext = new ResolveFieldContext(); resolveContext.FieldName = field.Name; resolveContext.FieldAst = field; resolveContext.FieldDefinition = fieldDefinition; resolveContext.ReturnType = fieldDefinition.ResolvedType; resolveContext.ParentType = parentType; resolveContext.Arguments = arguments; resolveContext.Source = source; resolveContext.Schema = context.Schema; resolveContext.Document = context.Document; resolveContext.Fragments = context.Fragments; resolveContext.RootValue = context.RootValue; resolveContext.UserContext = context.UserContext; resolveContext.Operation = context.Operation; resolveContext.Variables = context.Variables; resolveContext.CancellationToken = context.CancellationToken; resolveContext.Metrics = context.Metrics; resolveContext.Errors = context.Errors; resolveContext.Path = fieldPath; var subFields = SubFieldsFor(context, fieldDefinition.ResolvedType, field); resolveContext.SubFields = subFields; var resolver = fieldDefinition.Resolver ?? new NameFieldResolver(); var result = resolver.Resolve(resolveContext); if (result is Task) { var task = result as Task; if (task.IsFaulted) { var aggregateException = task.Exception; var exception = aggregateException.InnerExceptions.Count == 1 ? aggregateException.InnerException : aggregateException; return(GenerateError(resolveResult, field, context, exception, fieldPath)); } await task.ConfigureAwait(false); result = task.GetProperyValue("Result"); } resolveResult.Value = await CompleteValueAsync(context, parentType, fieldDefinition.ResolvedType, field, result, fieldPath).ConfigureAwait(false); return(resolveResult); } catch (Exception exc) { return(GenerateError(resolveResult, field, context, exc, path)); } }
public async Task<object> ExecuteFields(ExecutionContext context, ObjectGraphType rootType, object source, Dictionary<string, Fields> fields) { return await fields.ToDictionaryAsync( pair => pair.Key, pair => ResolveField(context, rootType, source, pair.Value)); }
/// <summary> /// Returns an instance of an <see cref="IExecutionStrategy"/> given specified execution parameters. /// <br/><br/> /// Typically the strategy is selected based on the type of operation. /// <br/><br/> /// By default, the selection is handled by the <see cref="IExecutionStrategySelector"/> implementation passed to the /// constructor, which will select an execution strategy based on a set of <see cref="ExecutionStrategyRegistration"/> /// instances passed to it. /// <br/><br/> /// For the <see cref="DefaultExecutionStrategySelector"/> without any registrations, /// query operations will return a <see cref="ParallelExecutionStrategy"/> while mutation operations return a /// <see cref="SerialExecutionStrategy"/>. Subscription operations return a <see cref="SubscriptionExecutionStrategy"/>. /// </summary> protected virtual IExecutionStrategy SelectExecutionStrategy(ExecutionContext context) => _executionStrategySelector.Select(context);
public Task<Dictionary<string, object>> ExecuteFieldsAsync(ExecutionContext context, IObjectGraphType rootType, object source, Dictionary<string, Fields> fields) { return fields.ToDictionaryAsync<KeyValuePair<string, Fields>, string, ResolveFieldResult<object>, object>( pair => pair.Key, pair => ResolveFieldAsync(context, rootType, source, pair.Value)); }
public async Task <ExecutionResult> ExecuteAsync(ExecutionOptions options) { if (options == null) { throw new ArgumentNullException(nameof(options)); } if (options.Schema == null) { throw new InvalidOperationException("Cannot execute request if no schema is specified"); } if (options.Query == null) { throw new InvalidOperationException("Cannot execute request if no query is specified"); } if (options.FieldMiddleware == null) { throw new InvalidOperationException("Cannot execute request if no middleware builder specified"); } var metrics = new Metrics(options.EnableMetrics).Start(options.OperationName); options.Schema.NameConverter = options.NameConverter; options.Schema.Filter = options.SchemaFilter; ExecutionResult result = null; ExecutionContext context = null; try { if (!options.Schema.Initialized) { using (metrics.Subject("schema", "Initializing schema")) { options.FieldMiddleware.ApplyTo(options.Schema); options.Schema.Initialize(); } } var document = options.Document; using (metrics.Subject("document", "Building document")) { if (document == null) { document = _documentBuilder.Build(options.Query); } } if (document.Operations.Count == 0) { throw new NoOperationError(); } var operation = GetOperation(options.OperationName, document); metrics.SetOperationName(operation?.Name); if (operation == null) { throw new InvalidOperationException($"Query does not contain operation '{options.OperationName}'."); } IValidationResult validationResult; using (metrics.Subject("document", "Validating document")) { validationResult = await _documentValidator.ValidateAsync( options.Query, options.Schema, document, options.ValidationRules, options.UserContext, options.Inputs); } if (options.ComplexityConfiguration != null && validationResult.IsValid) { using (metrics.Subject("document", "Analyzing complexity")) _complexityAnalyzer.Validate(document, options.ComplexityConfiguration); } context = BuildExecutionContext( options.Schema, options.Root, document, operation, options.Inputs, options.UserContext, options.CancellationToken, metrics, options.Listeners, options.ThrowOnUnhandledException, options.UnhandledExceptionDelegate, options.MaxParallelExecutionCount, options.RequestServices); foreach (var listener in options.Listeners) { await listener.AfterValidationAsync(context, validationResult) .ConfigureAwait(false); } if (!validationResult.IsValid) { return(new ExecutionResult { Errors = validationResult.Errors, Perf = metrics.Finish() }); } if (context.Errors.Count > 0) { return(new ExecutionResult { Errors = context.Errors, Perf = metrics.Finish() }); } using (metrics.Subject("execution", "Executing operation")) { if (context.Listeners != null) { foreach (var listener in context.Listeners) { await listener.BeforeExecutionAsync(context) .ConfigureAwait(false); } } IExecutionStrategy executionStrategy = SelectExecutionStrategy(context); if (executionStrategy == null) { throw new InvalidOperationException("Invalid ExecutionStrategy!"); } var task = executionStrategy.ExecuteAsync(context) .ConfigureAwait(false); if (context.Listeners != null) { foreach (var listener in context.Listeners) { await listener.BeforeExecutionAwaitedAsync(context) .ConfigureAwait(false); } } result = await task; if (context.Listeners != null) { foreach (var listener in context.Listeners) { await listener.AfterExecutionAsync(context) .ConfigureAwait(false); } } } if (context.Errors.Count > 0) { result.Errors = context.Errors; } } catch (OperationCanceledException) when(options.CancellationToken.IsCancellationRequested) { throw; } catch (ExecutionError ex) { result = new ExecutionResult { Errors = new ExecutionErrors { ex } }; } catch (Exception ex) { if (options.ThrowOnUnhandledException) { throw; } UnhandledExceptionContext exceptionContext = null; if (options.UnhandledExceptionDelegate != null) { exceptionContext = new UnhandledExceptionContext(context, null, ex); options.UnhandledExceptionDelegate(exceptionContext); ex = exceptionContext.Exception; } result = new ExecutionResult { Errors = new ExecutionErrors { ex is ExecutionError executionError ? executionError : new UnhandledError(exceptionContext?.ErrorMessage ?? "Error executing document.", ex) } }; } finally { result ??= new ExecutionResult(); result.Perf = metrics.Finish(); } return(result); }
public Task<Dictionary<string, object>> ExecuteOperationAsync(ExecutionContext context) { var rootType = GetOperationRootType(context.Document, context.Schema, context.Operation); var fields = CollectFields( context, rootType, context.Operation.SelectionSet, new Dictionary<string, Fields>(), new List<string>()); return ExecuteFieldsAsync(context, rootType, context.RootValue, fields); }
public ExecutionContext BuildExecutionContext( ISchema schema, object root, Document document, Operation operation, Inputs inputs, object userContext, CancellationToken cancellationToken, Metrics metrics) { var context = new ExecutionContext(); context.Document = document; context.Schema = schema; context.RootValue = root; context.UserContext = userContext; context.Operation = operation; context.Variables = GetVariableValues(document, schema, operation.Variables, inputs); context.Fragments = document.Fragments; context.CancellationToken = cancellationToken; context.Metrics = metrics; return context; }
/// <summary> /// Encapsulates an error within an <see cref="ExecutionResult"/> for errors generated /// by the event stream via <see cref="IObserver{T}.OnError(Exception)"/>. /// <br/><br/> /// Executes with a scoped service provider in <see cref="ExecutionContext.RequestServices"/> /// which is disposed once this method completes. /// </summary> protected override Task <ExecutionError> ProcessErrorAsync(ExecutionContext context, ExecutionNode node, Exception exception) { using var scope = _serviceScopeFactory.CreateScope(); context.RequestServices = scope.ServiceProvider; return(base.ProcessErrorAsync(context, node, exception)); }
public async Task <object> CompleteValue(ExecutionContext context, GraphType fieldType, Fields fields, object result) { if (fieldType is NonNullGraphType) { var nonNullType = fieldType as NonNullGraphType; var completed = await CompleteValue(context, context.Schema.FindType(nonNullType.Type), fields, result); if (completed == null) { throw new ExecutionError("Cannot return null for non-null type. Field: {0}".ToFormat(nonNullType.Name)); } return(completed); } if (result == null) { return(null); } if (fieldType is ScalarGraphType) { var scalarType = fieldType as ScalarGraphType; var coercedValue = scalarType.Coerce(result); return(coercedValue); } if (fieldType is ListGraphType) { var list = result as IEnumerable; if (list == null) { throw new ExecutionError("User error: expected an IEnumerable list though did not find one."); } var listType = fieldType as ListGraphType; var itemType = context.Schema.FindType(listType.Type); var results = await list.MapAsync(async item => { return(await CompleteValue(context, itemType, fields, item)); }); return(results); } var objectType = fieldType as ObjectGraphType; if (fieldType is InterfaceGraphType) { var interfaceType = fieldType as InterfaceGraphType; objectType = interfaceType.ResolveType(result); } if (objectType == null) { return(null); } var subFields = new Dictionary <string, Fields>(); fields.Apply(field => { subFields = CollectFields(context, objectType, field.Selections, subFields); }); return(await ExecuteFields(context, objectType, result, subFields)); }
public async Task<object> CompleteValue(ExecutionContext context, GraphType fieldType, Fields fields, object result) { var nonNullType = fieldType as NonNullGraphType; if (nonNullType != null) { var completed = await CompleteValue(context, context.Schema.FindType(nonNullType.Type), fields, result); if (completed == null) { throw new ExecutionError("Cannot return null for non-null type. Field: {0}".ToFormat(nonNullType.Name)); } return completed; } if (result == null) { return null; } if (fieldType is ScalarGraphType) { var scalarType = fieldType as ScalarGraphType; var coercedValue = scalarType.Coerce(result); return coercedValue; } if (fieldType is ListGraphType) { var list = result as IEnumerable; if (list == null) { throw new ExecutionError("User error: expected an IEnumerable list though did not find one."); } var listType = fieldType as ListGraphType; var itemType = context.Schema.FindType(listType.Type); var results = await list.MapAsync(async item => { return await CompleteValue(context, itemType, fields, item); }); return results; } var objectType = fieldType as ObjectGraphType; if (fieldType is InterfaceGraphType) { var interfaceType = fieldType as InterfaceGraphType; objectType = interfaceType.ResolveType(result); } if (objectType == null) { return null; } var subFields = new Dictionary<string, Fields>(); fields.Apply(field => { subFields = CollectFields(context, objectType, field.Selections, subFields); }); return await ExecuteFields(context, objectType, result, subFields); }
public async Task <ResolveFieldResult <object> > ResolveFieldAsync(ExecutionContext context, IObjectGraphType parentType, object source, Field field, IEnumerable <string> path) { context.CancellationToken.ThrowIfCancellationRequested(); var fieldPath = path?.ToList() ?? new List <string>(); var resolveResult = new ResolveFieldResult <object> { Skip = false }; var fieldDefinition = GetFieldDefinition(context.Document, context.Schema, parentType, field); if (fieldDefinition == null) { resolveResult.Skip = true; return(resolveResult); } var arguments = GetArgumentValues(context.Schema, fieldDefinition.Arguments, field.Arguments, context.Variables); try { var resolveContext = new ResolveFieldContext { FieldName = field.Name, FieldAst = field, FieldDefinition = fieldDefinition, ReturnType = fieldDefinition.ResolvedType, ParentType = parentType, Arguments = arguments, Source = source, Schema = context.Schema, Document = context.Document, Fragments = context.Fragments, RootValue = context.RootValue, UserContext = context.UserContext, Operation = context.Operation, Variables = context.Variables, CancellationToken = context.CancellationToken, Metrics = context.Metrics, Errors = context.Errors, Path = fieldPath }; var subFields = SubFieldsFor(context, fieldDefinition.ResolvedType, field); resolveContext.SubFields = subFields; var resolver = fieldDefinition.Resolver ?? new NameFieldResolver(); var result = resolver.Resolve(resolveContext); result = await UnwrapResultAsync(result) .ConfigureAwait(false); resolveResult.Value = await CompleteValueAsync(context, parentType, fieldDefinition.ResolvedType, field, result, fieldPath) .ConfigureAwait(false); return(resolveResult); } catch (Exception exc) { return(GenerateError(resolveResult, field, context, exc, path)); } }
public bool ShouldIncludeNode(ExecutionContext context, Directives directives) { if (directives != null) { var directive = directives.Find(DirectiveGraphType.Skip.Name); if (directive != null) { var values = GetArgumentValues( context.Schema, DirectiveGraphType.Skip.Arguments, directive.Arguments, context.Variables); return !((bool) values["if"]); } directive = directives.Find(DirectiveGraphType.Include.Name); if (directive != null) { var values = GetArgumentValues( context.Schema, DirectiveGraphType.Include.Arguments, directive.Arguments, context.Variables); return (bool) values["if"]; } } return true; }
public object ExecuteFields(ExecutionContext context, ObjectGraphType rootType, object source, Dictionary<string, Fields> fields) { var result = new Dictionary<string, object>(); fields.Apply(pair => { result[pair.Key] = ResolveField(context, rootType, source, pair.Value); }); return result; }
public async Task <ResolveFieldResult <object> > ResolveField(ExecutionContext context, ObjectGraphType parentType, object source, Fields fields) { context.CancellationToken.ThrowIfCancellationRequested(); var resolveResult = new ResolveFieldResult <object> { Skip = false }; var field = fields.First(); var fieldDefinition = GetFieldDefinition(context.Schema, parentType, field); if (fieldDefinition == null) { resolveResult.Skip = true; return(resolveResult); } var arguments = GetArgumentValues(context.Schema, fieldDefinition.Arguments, field.Arguments, context.Variables); Func <ResolveFieldContext, object> defaultResolve = (ctx) => { return(ctx.Source != null?GetProperyValue(ctx.Source, ctx.FieldAst.Name) : null); }; try { var resolveContext = new ResolveFieldContext(); resolveContext.FieldName = field.Name; resolveContext.FieldAst = field; resolveContext.FieldDefinition = fieldDefinition; resolveContext.ReturnType = context.Schema.FindType(fieldDefinition.Type); resolveContext.ParentType = parentType; resolveContext.Arguments = arguments; resolveContext.Source = source; resolveContext.Schema = context.Schema; resolveContext.Fragments = context.Fragments; resolveContext.RootValue = context.RootValue; resolveContext.Operation = context.Operation; resolveContext.Variables = context.Variables; resolveContext.CancellationToken = context.CancellationToken; var resolve = fieldDefinition.Resolve ?? defaultResolve; var result = resolve(resolveContext); if (result is Task) { var task = result as Task; await task; result = GetProperyValue(task, "Result"); } if (parentType is __Field && result is Type) { result = context.Schema.FindType(result as Type); } resolveResult.Value = await CompleteValue(context, context.Schema.FindType(fieldDefinition.Type), fields, result); return(resolveResult); } catch (Exception exc) { context.Errors.Add(new ExecutionError("Error trying to resolve {0}.".ToFormat(field.Name), exc)); resolveResult.Skip = false; return(resolveResult); } }
public Task <Dictionary <string, object> > ExecuteFieldsAsync(ExecutionContext context, IObjectGraphType rootType, object source, Dictionary <string, Field> fields, IEnumerable <string> path) { return(fields.ToDictionaryAsync <KeyValuePair <string, Field>, string, ResolveFieldResult <object>, object>( pair => pair.Key, pair => ResolveFieldAsync(context, rootType, source, pair.Value, path.Concat(new[] { pair.Key })))); }
public Dictionary <string, Field> CollectFields( ExecutionContext context, IGraphType specificType, SelectionSet selectionSet, Dictionary <string, Field> fields, List <string> visitedFragmentNames) { if (fields == null) { fields = new Dictionary <string, Field>(); } selectionSet?.Selections.Apply(selection => { if (selection is Field) { var field = (Field)selection; if (!ShouldIncludeNode(context, field.Directives)) { return; } var name = field.Alias ?? field.Name; fields[name] = field; } else if (selection is FragmentSpread) { var spread = (FragmentSpread)selection; if (visitedFragmentNames.Contains(spread.Name) || !ShouldIncludeNode(context, spread.Directives)) { return; } visitedFragmentNames.Add(spread.Name); var fragment = context.Fragments.FindDefinition(spread.Name); if (fragment == null || !ShouldIncludeNode(context, fragment.Directives) || !DoesFragmentConditionMatch(context, fragment.Type.Name, specificType)) { return; } CollectFields(context, specificType, fragment.SelectionSet, fields, visitedFragmentNames); } else if (selection is InlineFragment) { var inline = (InlineFragment)selection; var name = inline.Type != null ? inline.Type.Name : specificType.Name; if (!ShouldIncludeNode(context, inline.Directives) || !DoesFragmentConditionMatch(context, name, specificType)) { return; } CollectFields(context, specificType, inline.SelectionSet, fields, visitedFragmentNames); } }); return(fields); }
public object ResolveField(ExecutionContext context, ObjectGraphType parentType, object source, Fields fields) { var field = fields.First(); var fieldDefinition = GetFieldDefinition(context.Schema, parentType, field); if (fieldDefinition == null) { return null; } var arguments = GetArgumentValues(fieldDefinition.Arguments, field.Arguments, context.Variables); Func<ResolveFieldContext, object> defaultResolve = (ctx) => { return ctx.Source != null ? GetProperyValue(ctx.Source, ctx.FieldAst.Name) : null; }; try { var resolveContext = new ResolveFieldContext(); resolveContext.FieldAst = field; resolveContext.FieldDefinition = fieldDefinition; resolveContext.Schema = context.Schema; resolveContext.ParentType = parentType; resolveContext.Arguments = arguments; resolveContext.Source = source; var resolve = fieldDefinition.Resolve ?? defaultResolve; var result = resolve(resolveContext); return CompleteValue(context, fieldDefinition.Type, fields, result); } catch (Exception exc) { context.Errors.Add(new ExecutionError("Error trying to resolve {0}.".ToFormat(field.Name), exc)); return null; } }
public override Task <ExecutionResult> ExecuteAsync(GraphQL.Execution.ExecutionContext context) { Executed.ShouldBeFalse(); Executed = true; return(base.ExecuteAsync(context)); }
public async Task <object> CompleteValueAsync(ExecutionContext context, IObjectGraphType parentType, IGraphType fieldType, Field field, object result, IEnumerable <string> path) { var fieldName = field?.Name; var nonNullType = fieldType as NonNullGraphType; if (nonNullType != null) { var type = nonNullType.ResolvedType; var completed = await CompleteValueAsync(context, parentType, type, field, result, path).ConfigureAwait(false); if (completed == null) { var error = new ExecutionError("Cannot return null for non-null type. Field: {0}, Type: {1}!." .ToFormat(fieldName, type.Name)); error.AddLocation(field, context.Document); throw error; } return(completed); } if (result == null) { return(null); } if (fieldType is ScalarGraphType) { var scalarType = fieldType as ScalarGraphType; var coercedValue = scalarType.Serialize(result); return(coercedValue); } if (fieldType is ListGraphType) { var list = result as IEnumerable; if (list == null) { var error = new ExecutionError("User error: expected an IEnumerable list though did not find one."); error.AddLocation(field, context.Document); throw error; } var listType = fieldType as ListGraphType; var itemType = listType.ResolvedType; var results = await list .MapAsync(async (index, item) => await CompleteValueAsync(context, parentType, itemType, field, item, path.Concat(new[] { $"{index}" })).ConfigureAwait(false)) .ConfigureAwait(false); return(results); } var objectType = fieldType as IObjectGraphType; if (fieldType is IAbstractGraphType) { var abstractType = fieldType as IAbstractGraphType; objectType = abstractType.GetObjectType(result); if (objectType == null) { var error = new ExecutionError( $"Abstract type {abstractType.Name} must resolve to an Object type at " + $"runtime for field {parentType.Name}.{fieldName} " + $"with value {result}, received 'null'."); error.AddLocation(field, context.Document); throw error; } if (!abstractType.IsPossibleType(objectType)) { var error = new ExecutionError( "Runtime Object type \"{0}\" is not a possible type for \"{1}\"" .ToFormat(objectType, abstractType)); error.AddLocation(field, context.Document); throw error; } } if (objectType == null) { return(null); } if (objectType.IsTypeOf != null && !objectType.IsTypeOf(result)) { var error = new ExecutionError( "Expected value of type \"{0}\" but got: {1}." .ToFormat(objectType, result)); error.AddLocation(field, context.Document); throw error; } var subFields = new Dictionary <string, Field>(); var visitedFragments = new List <string>(); subFields = CollectFields(context, objectType, field?.SelectionSet, subFields, visitedFragments); return(await ExecuteFieldsAsync(context, objectType, result, subFields, path).ConfigureAwait(false)); }
public Dictionary <string, Fields> CollectFields( ExecutionContext context, GraphType specificType, Selections selections, Dictionary <string, Fields> fields, List <string> visitedFragmentNames) { if (fields == null) { fields = new Dictionary <string, Fields>(); } selections.Apply(selection => { if (selection.Field != null) { if (!ShouldIncludeNode(context, selection.Field.Directives)) { return; } var name = selection.Field.Alias ?? selection.Field.Name; if (!fields.ContainsKey(name)) { fields[name] = new Fields(); } fields[name].Add(selection.Field); } else if (selection.Fragment != null) { if (selection.Fragment is FragmentSpread) { var spread = selection.Fragment as FragmentSpread; if (visitedFragmentNames.Contains(spread.Name) || !ShouldIncludeNode(context, spread.Directives)) { return; } visitedFragmentNames.Add(spread.Name); var fragment = context.Fragments.FindDefinition(spread.Name); if (fragment == null || !ShouldIncludeNode(context, fragment.Directives) || !DoesFragmentConditionMatch(context, fragment, specificType)) { return; } CollectFields(context, specificType, fragment.Selections, fields, visitedFragmentNames); } else if (selection.Fragment is InlineFragment) { var inline = selection.Fragment as InlineFragment; if (!ShouldIncludeNode(context, inline.Directives) || !DoesFragmentConditionMatch(context, inline, specificType)) { return; } CollectFields(context, specificType, inline.Selections, fields, visitedFragmentNames); } } }); return(fields); }
public async Task<ResolveFieldResult<object>> ResolveFieldAsync(ExecutionContext context, IObjectGraphType parentType, object source, Fields fields) { context.CancellationToken.ThrowIfCancellationRequested(); var resolveResult = new ResolveFieldResult<object> { Skip = false }; var field = fields.First(); var fieldDefinition = GetFieldDefinition(context.Schema, parentType, field); if (fieldDefinition == null) { resolveResult.Skip = true; return resolveResult; } var arguments = GetArgumentValues(context.Schema, fieldDefinition.Arguments, field.Arguments, context.Variables); try { var resolveContext = new ResolveFieldContext(); resolveContext.FieldName = field.Name; resolveContext.FieldAst = field; resolveContext.FieldDefinition = fieldDefinition; resolveContext.ReturnType = fieldDefinition.ResolvedType; resolveContext.ParentType = parentType; resolveContext.Arguments = arguments; resolveContext.Source = source; resolveContext.Schema = context.Schema; resolveContext.Document = context.Document; resolveContext.Fragments = context.Fragments; resolveContext.RootValue = context.RootValue; resolveContext.UserContext = context.UserContext; resolveContext.Operation = context.Operation; resolveContext.Variables = context.Variables; resolveContext.CancellationToken = context.CancellationToken; resolveContext.Metrics = context.Metrics; var resolver = fieldDefinition.Resolver ?? new NameFieldResolver(); var result = resolver.Resolve(resolveContext); if (result is Task) { var task = result as Task; await task.ConfigureAwait(false); result = task.GetProperyValue("Result"); } resolveResult.Value = await CompleteValueAsync(context, fieldDefinition.ResolvedType, fields, result).ConfigureAwait(false); return resolveResult; } catch (Exception exc) { var error = new ExecutionError("Error trying to resolve {0}.".ToFormat(field.Name), exc); error.AddLocation(field, context.Document); context.Errors.Add(error); resolveResult.Skip = false; return resolveResult; } }
public Task <Dictionary <string, object> > ExecuteFieldsAsync(ExecutionContext context, IObjectGraphType rootType, object source, Dictionary <string, Fields> fields) { return(fields.ToDictionaryAsync <KeyValuePair <string, Fields>, string, ResolveFieldResult <object>, object>( pair => pair.Key, pair => ResolveFieldAsync(context, rootType, source, pair.Value))); }
public Task<object> ExecuteOperation(ExecutionContext context) { var rootType = GetOperationRootType(context.Schema, context.Operation); var fields = CollectFields(context, rootType, context.Operation.Selections, null); return ExecuteFields(context, rootType, context.RootObject, fields); }
public async Task<object> CompleteValueAsync(ExecutionContext context, IGraphType fieldType, Fields fields, object result) { var field = fields != null ? fields.FirstOrDefault() : null; var fieldName = field != null ? field.Name : null; var nonNullType = fieldType as NonNullGraphType; if (nonNullType != null) { var type = nonNullType.ResolvedType; var completed = await CompleteValueAsync(context, type, fields, result).ConfigureAwait(false); if (completed == null) { var error = new ExecutionError("Cannot return null for non-null type. Field: {0}, Type: {1}!." .ToFormat(fieldName, type.Name)); error.AddLocation(field, context.Document); throw error; } return completed; } if (result == null) { return null; } if (fieldType is ScalarGraphType) { var scalarType = fieldType as ScalarGraphType; var coercedValue = scalarType.Serialize(result); return coercedValue; } if (fieldType is ListGraphType) { var list = result as IEnumerable; if (list == null) { var error = new ExecutionError("User error: expected an IEnumerable list though did not find one."); error.AddLocation(field, context.Document); throw error; } var listType = fieldType as ListGraphType; var itemType = listType.ResolvedType; var results = await list.MapAsync(async item => await CompleteValueAsync(context, itemType, fields, item).ConfigureAwait(false)).ConfigureAwait(false); return results; } var objectType = fieldType as IObjectGraphType; if (fieldType is IAbstractGraphType) { var abstractType = fieldType as IAbstractGraphType; objectType = abstractType.GetObjectType(result); if (objectType != null && !abstractType.IsPossibleType(objectType)) { var error = new ExecutionError( "Runtime Object type \"{0}\" is not a possible type for \"{1}\"" .ToFormat(objectType, abstractType)); error.AddLocation(field, context.Document); throw error; } } if (objectType == null) { return null; } if (objectType.IsTypeOf != null && !objectType.IsTypeOf(result)) { var error = new ExecutionError( "Expected value of type \"{0}\" but got: {1}." .ToFormat(objectType, result)); error.AddLocation(field, context.Document); throw error; } var subFields = new Dictionary<string, Fields>(); var visitedFragments = new List<string>(); fields.Apply(f => { subFields = CollectFields(context, objectType, f.SelectionSet, subFields, visitedFragments); }); return await ExecuteFieldsAsync(context, objectType, result, subFields).ConfigureAwait(false); }
public async Task<object> ResolveField(ExecutionContext context, ObjectGraphType parentType, object source, Fields fields) { context.CancellationToken.ThrowIfCancellationRequested(); var field = fields.First(); var fieldDefinition = GetFieldDefinition(context.Schema, parentType, field); if (fieldDefinition == null) { return null; } var arguments = GetArgumentValues(context.Schema, fieldDefinition.Arguments, field.Arguments, context.Variables); Func<ResolveFieldContext, object> defaultResolve = (ctx) => { return ctx.Source != null ? GetProperyValue(ctx.Source, ctx.FieldAst.Name) : null; }; try { var resolveContext = new ResolveFieldContext(); resolveContext.FieldAst = field; resolveContext.FieldDefinition = fieldDefinition; resolveContext.Schema = context.Schema; resolveContext.ParentType = parentType; resolveContext.Arguments = arguments; resolveContext.Source = source; resolveContext.CancellationToken = context.CancellationToken; var resolve = fieldDefinition.Resolve ?? defaultResolve; var result = resolve(resolveContext); if(result is Task) { var task = result as Task; await task; result = GetProperyValue(task, "Result"); } if (parentType is __Field && result is Type) { result = context.Schema.FindType(result as Type); } return await CompleteValue(context, context.Schema.FindType(fieldDefinition.Type), fields, result); } catch (Exception exc) { context.Errors.Add(new ExecutionError("Error trying to resolve {0}.".ToFormat(field.Name), exc)); return null; } }
public Dictionary<string, Fields> CollectFields( ExecutionContext context, IGraphType specificType, SelectionSet selectionSet, Dictionary<string, Fields> fields, List<string> visitedFragmentNames) { if (fields == null) { fields = new Dictionary<string, Fields>(); } selectionSet.Selections.Apply(selection => { if (selection is Field) { var field = (Field)selection; if (!ShouldIncludeNode(context, field.Directives)) { return; } var name = field.Alias ?? field.Name; if (!fields.ContainsKey(name)) { fields[name] = new Fields(); } fields[name].Add(field); } else if (selection is FragmentSpread) { var spread = (FragmentSpread)selection; if (visitedFragmentNames.Contains(spread.Name) || !ShouldIncludeNode(context, spread.Directives)) { return; } visitedFragmentNames.Add(spread.Name); var fragment = context.Fragments.FindDefinition(spread.Name); if (fragment == null || !ShouldIncludeNode(context, fragment.Directives) || !DoesFragmentConditionMatch(context, fragment.Type.Name, specificType)) { return; } CollectFields(context, specificType, fragment.SelectionSet, fields, visitedFragmentNames); } else if (selection is InlineFragment) { var inline = (InlineFragment)selection; var name = inline.Type != null ? inline.Type.Name : specificType.Name; if (!ShouldIncludeNode(context, inline.Directives) || !DoesFragmentConditionMatch(context, name, specificType)) { return; } CollectFields(context, specificType, inline.SelectionSet, fields, visitedFragmentNames); } }); return fields; }
public Dictionary<string, Fields> CollectFields(ExecutionContext context, GraphType type, Selections selections, Dictionary<string, Fields> fields) { if (fields == null) { fields = new Dictionary<string, Fields>(); } selections.Apply(selection => { if (selection.Field != null) { if (!ShouldIncludeNode(context, selection.Field.Directives)) { return; } var name = selection.Field.Alias ?? selection.Field.Name; if (!fields.ContainsKey(name)) { fields[name] = new Fields(); } fields[name].Add(selection.Field); } else if (selection.Fragment != null) { if (selection.Fragment is FragmentSpread) { var spread = selection.Fragment as FragmentSpread; if (!ShouldIncludeNode(context, spread.Directives)) { return; } var fragment = context.Fragments.FindDefinition(spread.Name); if (!ShouldIncludeNode(context, fragment.Directives) || !DoesFragmentConditionMatch(context, fragment, type)) { return; } CollectFields(context, type, fragment.Selections, fields); } else if (selection.Fragment is InlineFragment) { var inline = selection.Fragment as InlineFragment; if (!ShouldIncludeNode(context, inline.Directives) || !DoesFragmentConditionMatch(context, inline, type)) { return; } CollectFields(context, type, inline.Selections, fields); } } }); return fields; }
public bool ShouldIncludeNode(ExecutionContext context, Directives directives) { if (directives != null) { var directive = directives.Find(DirectiveGraphType.Skip.Name); if (directive != null) { var values = GetArgumentValues( context.Schema, DirectiveGraphType.Skip.Arguments, directive.Arguments, context.Variables); object ifObj; values.TryGetValue("if", out ifObj); bool ifVal; return !(bool.TryParse(ifObj?.ToString() ?? string.Empty, out ifVal) && ifVal); } directive = directives.Find(DirectiveGraphType.Include.Name); if (directive != null) { var values = GetArgumentValues( context.Schema, DirectiveGraphType.Include.Arguments, directive.Arguments, context.Variables); object ifObj; values.TryGetValue("if", out ifObj); bool ifVal; return bool.TryParse(ifObj?.ToString() ?? string.Empty, out ifVal) && ifVal; } } return true; }
public bool DoesFragmentConditionMatch(ExecutionContext context, IHaveFragmentType fragment, GraphType type) { var conditionalType = context.Schema.FindType(fragment.Type); if (conditionalType == type) { return true; } if (conditionalType is InterfaceGraphType) { var interfaceType = (InterfaceGraphType) conditionalType; var hasInterfaces = type as IImplementInterfaces; if (hasInterfaces != null) { var interfaces = context.Schema.FindTypes(hasInterfaces.Interfaces); return interfaceType.IsPossibleType(interfaces); } } return false; }
public bool DoesFragmentConditionMatch(ExecutionContext context, string fragmentName, IGraphType type) { if (string.IsNullOrWhiteSpace(fragmentName)) { return true; } var conditionalType = context.Schema.FindType(fragmentName); if (conditionalType == null) { return false; } if (conditionalType.Equals(type)) { return true; } if (conditionalType is IAbstractGraphType) { var abstractType = (IAbstractGraphType)conditionalType; return abstractType.IsPossibleType(type); } return false; }
public async Task <ResolveFieldResult <object> > ResolveFieldAsync(ExecutionContext context, IObjectGraphType parentType, object source, Fields fields) { context.CancellationToken.ThrowIfCancellationRequested(); var resolveResult = new ResolveFieldResult <object> { Skip = false }; var field = fields.First(); var fieldDefinition = GetFieldDefinition(context.Schema, parentType, field); if (fieldDefinition == null) { resolveResult.Skip = true; return(resolveResult); } var arguments = GetArgumentValues(context.Schema, fieldDefinition.Arguments, field.Arguments, context.Variables); try { var resolveContext = new ResolveFieldContext(); resolveContext.FieldName = field.Name; resolveContext.FieldAst = field; resolveContext.FieldDefinition = fieldDefinition; resolveContext.ReturnType = fieldDefinition.ResolvedType; resolveContext.ParentType = parentType; resolveContext.Arguments = arguments; resolveContext.Source = source; resolveContext.Schema = context.Schema; resolveContext.Document = context.Document; resolveContext.Fragments = context.Fragments; resolveContext.RootValue = context.RootValue; resolveContext.UserContext = context.UserContext; resolveContext.Operation = context.Operation; resolveContext.Variables = context.Variables; resolveContext.CancellationToken = context.CancellationToken; resolveContext.Metrics = context.Metrics; var resolver = fieldDefinition.Resolver ?? new NameFieldResolver(); var result = resolver.Resolve(resolveContext); if (result is Task) { var task = result as Task; await task.ConfigureAwait(false); result = task.GetProperyValue("Result"); } resolveResult.Value = await CompleteValueAsync(context, fieldDefinition.ResolvedType, fields, result).ConfigureAwait(false); return(resolveResult); } catch (Exception exc) { var error = new ExecutionError("Error trying to resolve {0}.".ToFormat(field.Name), exc); error.AddLocation(field, context.Document); context.Errors.Add(error); resolveResult.Skip = false; return(resolveResult); } }
public async Task<ResolveFieldResult<object>> ResolveFieldAsync(ExecutionContext context, ObjectGraphType parentType, object source, Fields fields) { context.CancellationToken.ThrowIfCancellationRequested(); var resolveResult = new ResolveFieldResult<object> { Skip = false }; var field = fields.First(); var fieldDefinition = GetFieldDefinition(context.Schema, parentType, field); if (fieldDefinition == null) { resolveResult.Skip = true; return resolveResult; } var arguments = GetArgumentValues(context.Schema, fieldDefinition.Arguments, field.Arguments, context.Variables); Func<ResolveFieldContext, object> defaultResolve = ctx => ctx.Source != null ? GetProperyValue(ctx.Source, ctx.FieldAst.Name) : null; try { var resolveContext = new ResolveFieldContext(); resolveContext.FieldName = field.Name; resolveContext.FieldAst = field; resolveContext.FieldDefinition = fieldDefinition; resolveContext.ReturnType = context.Schema.FindType(fieldDefinition.Type); resolveContext.ParentType = parentType; resolveContext.Arguments = arguments; resolveContext.Source = source; resolveContext.Schema = context.Schema; resolveContext.Fragments = context.Fragments; resolveContext.RootValue = context.RootValue; resolveContext.Operation = context.Operation; resolveContext.Variables = context.Variables; resolveContext.CancellationToken = context.CancellationToken; var resolve = fieldDefinition.Resolve ?? defaultResolve; var result = resolve(resolveContext); if(result is Task) { var task = result as Task; await task.ConfigureAwait(false); result = GetProperyValue(task, "Result"); } if (parentType is __Field && result is Type) { result = context.Schema.FindType(result as Type); } resolveResult.Value = await CompleteValueAsync(context, context.Schema.FindType(fieldDefinition.Type), fields, result).ConfigureAwait(false); return resolveResult; } catch (Exception exc) { var error = new ExecutionError("Error trying to resolve {0}.".ToFormat(field.Name), exc); error.AddLocation(field.SourceLocation.Line, field.SourceLocation.Column); context.Errors.Add(error); resolveResult.Skip = false; return resolveResult; } }