public static bool HasCustomResolver(this GraphField field) { Guard.ArgumentNotNull(field, nameof(field)); return(field.Properties.TryGetValue(GraphDefaults.PropertyNames.HasCustomResolvers, out var value) ? (bool)value : false); }
private IGraphType CreateGraphType(OperationType operationType, IEnumerable <GraphOperationDescriptor> operations) { var graphType = new GraphType(operationType); if (operations == null) { return(graphType); } foreach (var operation in operations) { var resolver = new OperationResolver(operation, _binderProvider); var type = _graphTypeProvider.GetGraphType(operation.MethodInfo.ReturnType, null, null); var field = new GraphField(operation.Name, type, typeof(void), resolver); foreach (var parameter in operation.Parameters.Values) { if (!parameter.IsGraphArgument) { continue; } var parameterGraphType = _graphTypeProvider.GetGraphType(parameter.ParameterInfo.ParameterType, parameter.IsRequired, null); field.AddArgument(new NamedGraphType(parameter.ArgumentName, parameterGraphType)); } graphType.AddField(typeof(void), field); } return(graphType); }
/// <summary> /// Generates the query result class generator. /// </summary> /// <param name="selection">The <see cref="T:Dora.GraphQL.Selections.IFieldSelection" /> represents the selection node.</param> /// <param name="field">The <see cref="T:Dora.GraphQL.GraphTypes.GraphField" /> specific to the selection node.</param> /// <returns> /// The generated query result class. /// </returns> public Type Generate(IFieldSelection selection, GraphField field) { _log4GenerateQueryResultType(_logger, DateTimeOffset.Now, field.GraphType.Type.AssemblyQualifiedName, null); var assemblyName = new AssemblyName($"QueryResult{GetSurffix()}"); var assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run); var moduleBuilder = assemblyBuilder.DefineDynamicModule($"{assemblyName}.dll"); return(Generate(selection, field, moduleBuilder)); }
private Type Generate(IFieldSelection selection, GraphField graphField, ModuleBuilder moduleBuilder) { var methodAttributes = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual | MethodAttributes.Final; var typeName = $"{graphField.GraphType.Type.Name}{GetSurffix()}"; var typeBuilder = moduleBuilder.DefineType(typeName, TypeAttributes.Public); foreach (IFieldSelection subSelection in selection.SelectionSet) { var subField = graphField.GraphType.Fields.Values.Single(it => it.Name == subSelection.Name); var fieldName = $"_{subSelection.Name}"; Type propertyType; if (subSelection.SelectionSet.Count > 0) { if (subField.GraphType.IsEnumerable) { var elementType = Generate(subSelection, subField, moduleBuilder); propertyType = typeof(List <>).MakeGenericType(elementType); } else { propertyType = Generate(subSelection, subField, moduleBuilder); } } else { if (subField.GraphType.IsEnumerable) { propertyType = typeof(List <>).MakeGenericType(subField.GraphType.Type); } else { propertyType = subField.GraphType.Type; } } var field = typeBuilder.DefineField(fieldName, propertyType, FieldAttributes.Private); var get = typeBuilder.DefineMethod($"get_{subSelection.Name}", methodAttributes, propertyType, Type.EmptyTypes); var il = get.GetILGenerator(); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, field); il.Emit(OpCodes.Ret); var set = typeBuilder.DefineMethod($"set_{subSelection.Name}", methodAttributes, typeof(void), new Type[] { propertyType }); il = set.GetILGenerator(); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Stfld, field); il.Emit(OpCodes.Ret); var pb = typeBuilder.DefineProperty(subSelection.Name, PropertyAttributes.None, propertyType, Type.EmptyTypes); pb.SetGetMethod(get); pb.SetSetMethod(set); } return(typeBuilder.CreateTypeInfo()); }
/// <summary> /// Initializes a new instance of the <see cref="GraphContext"/> class. /// </summary> /// <param name="operationName">Name of the operation.</param> /// <param name="operationType">Type of the operation.</param> /// <param name="operation">The operation.</param> /// <param name="requestServices">The request services.</param> public GraphContext(string operationName, OperationType operationType, GraphField operation, IServiceProvider requestServices) { OperationName = operationName; OperationType = operationType; Operation = Guard.ArgumentNotNull(operation, nameof(operation)); RequestServices = Guard.ArgumentNotNull(requestServices, nameof(requestServices)); Arguments = new Dictionary <string, NamedGraphType>(); SelectionSet = new Collection <ISelectionNode>(); Variables = new Dictionary <string, object>(); Properties = new Dictionary <string, object>(); }
/// <summary> /// Creates graph field from <paramref name="graph"/> /// </summary> /// <param name="graph"></param> /// <returns>Graph field</returns> public IGraphField CreateGraphField(IGraph graph) { if (graph is Graph2D graph2D) { var graphField = new GraphField(graph2D.Width, graph2D.Length); graph.ForEach(graphField.Add); return(graphField); } throw new ArgumentException(nameof(graph)); }
private static bool IncludeAllMembers(IFieldSelection fieldSelection, GraphField field) { var fieldNames = field.GraphType.Fields.Values.Select(it => it.Name).Distinct().ToArray(); var selectedFieldNames = fieldSelection.SelectionSet.OfType <IFieldSelection>().Select(it => it.Name).Distinct().ToArray(); var invalidFieldNames = selectedFieldNames.Except(fieldNames); if (invalidFieldNames.Any()) { throw new GraphException($"Specified field(s) '{string.Join(", ", invalidFieldNames)}' is/are not defined in the GraphType '{field.GraphType.Name}'"); } return(fieldNames.Length == selectedFieldNames.Length); }
/// <summary> /// Initializes a new instance of the <see cref="GraphSchema"/> class. /// </summary> /// <param name="query">The query.</param> /// <param name="mutation">The mutation.</param> /// <param name="subsription">The subsription.</param> public GraphSchema(IGraphType query, IGraphType mutation, IGraphType subsription) { Query = query ?? throw new ArgumentNullException(nameof(query)); Mutation = mutation ?? throw new ArgumentNullException(nameof(mutation)); Subscription = subsription ?? throw new ArgumentNullException(nameof(subsription)); Fields = new Dictionary <NamedType, GraphField>(); var @void = typeof(void); var resolver = FakeResolver.Instance; var queryField = new GraphField(GraphDefaults.GraphSchema.QueryFieldName, query, @void, resolver); var mutationField = new GraphField(GraphDefaults.GraphSchema.MutationFieldName, mutation, @void, resolver); var subscriptionField = new GraphField(GraphDefaults.GraphSchema.SubscriptionFieldName, subsription, @void, resolver); Fields.Add(new NamedType(GraphDefaults.GraphSchema.QueryFieldName, @void), queryField); Fields.Add(new NamedType(GraphDefaults.GraphSchema.MutationFieldName, @void), mutationField); Fields.Add(new NamedType(GraphDefaults.GraphSchema.SubscriptionFieldName, @void), subscriptionField); }
public static bool SetHasCustomResolverFlags(this GraphField field) { Guard.ArgumentNotNull(field, nameof(field)); bool?flag = null; if (field.Resolver is MethodResolver) { flag = true; } foreach (var subField in field.GraphType.Fields.Values) { if (SetHasCustomResolverFlags(subField)) { flag = true; } } if (flag == true) { field.Properties[GraphDefaults.PropertyNames.HasCustomResolvers] = true; return(true); } return(false); }
public static bool TryGetGetField(this IDictionary <NamedType, GraphField> fields, Type type, string name, out GraphField field) { if (fields.TryGetValue(new NamedType(name, type), out field)) { return(true); } var baseType = type.BaseType; if (baseType != null && TryGetGetField(fields, baseType, name, out field)) { return(true); } foreach (var @interface in type.GetInterfaces()) { if (TryGetGetField(fields, @interface, name, out field)) { return(true); } } return((field = null) != null); }
public static bool TryGetGetField(this IDictionary <NamedType, GraphField> fields, object container, string name, out GraphField field) { Guard.ArgumentNotNull(container, nameof(container)); return(fields.TryGetGetField(container.GetType(), name, out field)); }
/// <summary> /// Adds a new the field in the given <see cref="IGraphType"/>. /// </summary> /// <param name="graphType">The <see cref="IGraphType"/> in which the new field is added.</param> /// <param name="containerType">The CLR type in which the added field is defined.</param> /// <param name="graphField">The <see cref="GraphField"/> to add.</param> /// <returns>The given <see cref="IGraphType"/>.</returns> public static IGraphType AddField(this IGraphType graphType, Type containerType, GraphField graphField) { Guard.ArgumentNotNull(graphType, nameof(graphType)); Guard.ArgumentNotNull(containerType, nameof(containerType)); Guard.ArgumentNotNull(graphField, nameof(graphField)); graphType.Fields.Add(new NamedType(graphField.Name, containerType), graphField); return(graphType); }
public static GraphField AddArgument(this GraphField field, NamedGraphType argument) { Guard.ArgumentNotNull(field, nameof(field)); field.Arguments.Add(argument.Name, argument); return(field); }
public static bool SetIncludeAllFieldsFlags( this IFieldSelection selection, GraphField graphField, IQueryResultTypeGenerator typeGenerator, ref bool generateQueryResultType, out bool isSubQueryTree) { Guard.ArgumentNotNull(selection, nameof(selection)); Guard.ArgumentNotNull(graphField, nameof(graphField)); EnsureSpecifyRequiredArguments(selection, graphField); isSubQueryTree = true; bool?flags = null; if (graphField.HasCustomResolver() || selection.Directives.Any() || selection.SelectionSet.Any(it => it is IFragment)) { generateQueryResultType = false; isSubQueryTree = false; flags = false; } var subFieldSelections = selection.SelectionSet.OfType <IFieldSelection>().ToArray(); foreach (var subSelection in subFieldSelections) { var subFields = graphField.GraphType.Fields.Values.Where(it => it.Name == subSelection.Name).ToArray(); if (subFields.Length > 1) { throw new GraphException($"{graphField.GraphType.Name} is a union GraphType, please perform query using fragement."); } if (subFields.Length == 0) { throw new GraphException($"Field '{subSelection.Name}' is not defined in the GraphType '{graphField.GraphType.Name}'"); } if (!SetIncludeAllFieldsFlags(subSelection, subFields[0], typeGenerator, ref generateQueryResultType, out var isSubtree)) { flags = false; if (!isSubtree) { isSubQueryTree = false; } } } var fragements = selection.SelectionSet.OfType <IFragment>().ToArray(); foreach (var fragement in fragements) { foreach (IFieldSelection fieldSelection in fragement.SelectionSet) { var fields = fragement.GraphType.Fields.Values.Where(it => it.Name == fieldSelection.Name).ToArray(); if (fields.Length > 1) { throw new GraphException($"{graphField.GraphType.Name} is a union GraphType, please perform query using fragement."); } if (fields.Length == 0) { throw new GraphException($"Field '{fieldSelection.Name}' is not defined in the GraphType '{fragement.GraphType.Name}'"); } if (!SetIncludeAllFieldsFlags(fieldSelection, fields[0], typeGenerator, ref generateQueryResultType, out var isSubtree)) { flags = false; if (!isSubtree) { isSubQueryTree = false; } } } } if (isSubQueryTree == false) { selection.Properties[GraphDefaults.PropertyNames.IsSubQueryTree] = false; } else { if (graphField.GraphType.Fields.Any() && generateQueryResultType) { selection.Properties[GraphDefaults.PropertyNames.QueryResultType] = typeGenerator.Generate(selection, graphField); selection.Properties[GraphDefaults.PropertyNames.IsSubQueryTree] = false; } } if (!IncludeAllMembers(selection, graphField) || flags == false) { selection.Properties[GraphDefaults.PropertyNames.IncludeAllFields] = false; return(false); } selection.Properties[GraphDefaults.PropertyNames.IncludeAllFields] = true; return(true); }
private static void EnsureSpecifyRequiredArguments(IFieldSelection fieldSelection, GraphField field) { var argumentNames = field.Arguments.Values .Where(it => it.GraphType.IsRequired) .Select(it => it.Name) .Except(fieldSelection.Arguments.Keys) .ToArray(); if (argumentNames.Any()) { throw new GraphException($"The mandatory argument(s) '{string.Join(", ", argumentNames)}' is/are not provided."); } }