private static EventDescription CreateEvent( IResolverContext executionContext) { IReadOnlyList <IFieldSelection> selections = executionContext.CollectFields( executionContext.RootType, executionContext.Operation.SelectionSet); if (selections.Count == 1) { IFieldSelection selection = selections[0]; var arguments = new List <ArgumentNode>(); IVariableValueCollection variables = executionContext.Variables; foreach (ArgumentNode argument in selection.Selection.Arguments) { if (argument.Value is VariableNode v) { IValueNode value = variables.GetVariable <IValueNode>(v.Name.Value); arguments.Add(argument.WithValue(value)); } else { arguments.Add(argument); } } return(new EventDescription(selection.Field.Name, arguments)); } else { throw new QueryException(CoreResources.Subscriptions_SingleRootField); } }
protected override void LeaveObject(IFieldSelection selection) { if (selection.Field.Member is PropertyInfo member) { SelectionClosure closure = Closures.Pop(); MemberInitExpression memberInit = closure.CreateMemberInit(); MemberExpression property = Expression.Property( Closures.Peek().Instance.Peek(), member); Expression withNullCheck = Expression.Condition( Expression.Equal(property, Expression.Constant(null)), Expression.Default(memberInit.Type), memberInit); Closures.Peek().Projections[selection.Field.Name] = Expression.Bind(selection.Field.Member, withNullCheck); base.LeaveObject(selection); } else { throw new QueryException( ErrorBuilder.New() .SetMessage( string.Format( "UseSelection is in a invalid state. Field {0}" + " should never have been visited!", selection.Field.Name)) .Build()); } }
/// <summary> /// Initializes a new instance of the <see cref="ResolverContext"/> struct. /// </summary> /// <param name="graphContext">The graph context.</param> /// <param name="field">The current selection field specific <see cref="GraphField"/>.</param> /// <param name="selection">The selection field.</param> /// <param name="container">The container representing the value of parent selection node.</param> public ResolverContext(GraphContext graphContext, GraphField field, IFieldSelection selection, object container) { Container = container; GraphContext = Guard.ArgumentNotNull(graphContext, nameof(graphContext)); Field = Guard.ArgumentNotNull(field, nameof(field)); Selection = Guard.ArgumentNotNull(selection, nameof(selection)); }
public Expression HandleLeave( SelectionVisitorContext context, IFieldSelection selection, Expression expression) { var argumentName = context.SelectionContext.FilterArgumentName; if (context.TryGetValueNode(argumentName, out IValueNode? filter) && selection.Field.Arguments[argumentName].Type is InputObjectType iot && iot is IFilterInputType fit) { var visitorContext = new QueryableFilterVisitorContext( iot, fit.EntityType, context.Conversion, false); QueryableFilterVisitor.Default.Visit(filter, visitorContext); return(Expression.Call( typeof(Enumerable), "Where", new[] { fit.EntityType }, expression, visitorContext.CreateFilter())); } return(expression); }
public static bool IsSubQueryTree(this IFieldSelection field) { Guard.ArgumentNotNull(field, nameof(field)); return(field.Properties.TryGetValue(GraphDefaults.PropertyNames.IsSubQueryTree, out var value) ? (bool)value : false); }
protected override bool EnterLeaf(IFieldSelection selection) { if (IntrospectionFields.TypeName.Equals(selection.Field.Name)) { return(false); } return(base.EnterLeaf(selection)); }
private IFieldSelection GetOffsetBasedPagingFieldOrDefault(IFieldSelection selection) { if (selection.Field.Name == "items") { return(selection); } return(null); }
/// <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()); }
public static bool TryGetQueryResultType(this IFieldSelection field, out Type type) { Guard.ArgumentNotNull(field, nameof(field)); if (field.Properties.TryGetValue(GraphDefaults.PropertyNames.QueryResultType, out var value)) { type = (Type)value; return(true); } return((type = null) != null); }
protected override void LeaveLeaf(IFieldSelection selection) { if (selection.Field.Member is PropertyInfo member) { SelectionClosure closure = Closures.Peek(); closure.Projections[member.Name] = Expression.Bind( member, Expression.Property(closure.Instance.Peek(), member)); } base.LeaveLeaf(selection); }
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); }
public ExtractedField ExtractField( NameString sourceSchema, DocumentNode document, OperationDefinitionNode operation, IFieldSelection selection, INamedOutputType declaringType) { if (document == null) { throw new ArgumentNullException(nameof(document)); } if (operation == null) { throw new ArgumentNullException(nameof(operation)); } if (selection == null) { throw new ArgumentNullException(nameof(selection)); } if (declaringType == null) { throw new ArgumentNullException(nameof(declaringType)); } sourceSchema.EnsureNotEmpty(nameof(sourceSchema)); var context = new Context( sourceSchema, declaringType, document, operation); var syntaxNodes = new List <FieldNode>(); foreach (FieldNode syntaxNode in selection.SyntaxNodes) { FieldNode field = RewriteField(syntaxNode, context); if (selection.Field.Type.NamedType().IsLeafType() || (field.SelectionSet is not null && field.SelectionSet.Selections.Count > 0)) { syntaxNodes.Add(field); } } return(new ExtractedField( syntaxNodes, context.Variables.Values.ToList(), context.Fragments.Values.ToList())); }
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."); } }
private bool HasArguments(IFieldSelection selection) { if (selection.Arguments.Values.Any(it => !it.IsVaribleReference)) { return(true); } foreach (var subField in selection.SelectionSet.OfType <IFieldSelection>()) { if (HasArguments(subField)) { return(true); } } return(false); }
protected override bool EnterList(IFieldSelection selection) { if (selection.Field.Member is PropertyInfo) { (IOutputType type, SelectionSetNode? selectionSet) = UnwrapPaging(selection.Field.Type, selection.Selection.SelectionSet); Type clrType = type.IsListType() ? type.ElementType().ToClrType() : type.ToClrType(); Closures.Push(new SelectionClosure(clrType, "e" + Closures.Count)); return(VisitSelections(type, selectionSet)); } return(false); }
public Expression HandleLeave( SelectionVisitorContext context, IFieldSelection selection, Expression expression) { if (context.TryGetValueNode(ArgumentName, out IValueNode sortArgument) && selection.Field.Arguments[ArgumentName].Type is InputObjectType iot && iot is ISortInputType fit) { var visitor = new QueryableSortVisitor(iot, fit.EntityType); sortArgument.Accept(visitor); return(visitor.Compile(expression)); } return(expression); }
protected override bool EnterObject(IFieldSelection selection) { if (selection.Field.Member is PropertyInfo property) { var nextClosure = new SelectionClosure( selection.Field.ClrType, "e" + Closures.Count); nextClosure.Instance.Push( Expression.Property( Closures.Peek().Instance.Peek(), property)); Closures.Push(nextClosure); return(base.EnterObject(selection)); } return(false); }
private (IOutputType, SelectionSetNode) MergeSelection( SelectionSetNode selectionSet, IFieldSelection selection) { if (selectionSet == null) { selectionSet = selection.Selection.SelectionSet; } else { selectionSet = selectionSet.WithSelections( selectionSet.Selections.Concat( selection.Selection.SelectionSet.Selections) .ToList()); } return(selection.Field.Type, selectionSet); }
private static void CollectSelections( IResolverContext context, IFieldSelection selection, ICollection <IFieldSelection> collected) { if (selection.Field.Type.IsLeafType()) { collected.Add(selection); } if (selection.Field.Type.NamedType() is ObjectType objectType) { foreach (IFieldSelection child in context.GetSelections( objectType, selection.SyntaxNode.SelectionSet)) { CollectSelections(context, child, collected); } } }
protected override void LeaveList(IFieldSelection selection) { if (selection.Field.Member is PropertyInfo propertyInfo) { SelectionClosure closure = Closures.Pop(); Expression body = Expression.Property( Closures.Peek().Instance.Peek(), propertyInfo); if (selection is FieldSelection fieldSelection) { var context = new SelectionVisitorContext( Context, _converter, fieldSelection, _selectionMiddlewareContext); for (var i = 0; i < _listHandler.Count; i++) { body = _listHandler[i].HandleLeave(context, selection, body); } } Expression select = closure.CreateSelection(body, propertyInfo.PropertyType); Closures.Peek().Projections[selection.Field.Name] = Expression.Bind(selection.Field.Member, select); base.LeaveList(selection); } else { throw new QueryException( ErrorBuilder.New() .SetMessage( string.Format( "UseSelection is in a invalid state. Field {0}" + " should never have been visited!", selection.Field.Name)) .Build()); } }
public Expression HandleLeave( SelectionVisitorContext context, IFieldSelection selection, Expression expression) { var argumentName = context.SelectionContext.SortingArgumentName; if (context.TryGetValueNode(argumentName, out IValueNode? sortArgument) && selection.Field.Arguments[argumentName].Type is InputObjectType iot && iot is ISortInputType fit) { var visitorContext = new QueryableSortVisitorContext( iot, fit.EntityType, false); QueryableSortVisitor.Default.Visit(sortArgument, visitorContext); return(visitorContext.Compile(expression)); } return(expression); }
public Expression HandleLeave( SelectionVisitorContext context, IFieldSelection selection, Expression expression) { IFilterConvention convention = context.SelectionContext.FilterConvention; NameString argumentName = convention.GetArgumentName(); if (context.TryGetValueNode(argumentName, out IValueNode? filter) && selection.Field.Arguments[argumentName].Type is InputObjectType iot && iot is IFilterInputType fit && convention.TryGetVisitorDefinition( out FilterExpressionVisitorDefinition? defintion)) { var visitorContext = new QueryableFilterVisitorContext( iot, fit.EntityType, defintion, context.Conversion, false); QueryableFilterVisitor.Default.Visit(filter, visitorContext); if (visitorContext.TryCreateLambda( out LambdaExpression? filterExpression)) { return(Expression.Call( typeof(Enumerable), nameof(Enumerable.Where), new[] { fit.EntityType }, expression, filterExpression)); } else { context.ReportErrors(visitorContext.Errors); } } return(expression); }
private bool TryUnwrapOffsetBasedPaging( IOutputType outputType, SelectionSetNode selectionSet, out (IOutputType, SelectionSetNode) result) { result = (null, null); if (outputType.NamedType() is ObjectType type) { foreach (IFieldSelection selection in Context.CollectFields(type, selectionSet)) { IFieldSelection currentSelection = GetOffsetBasedPagingFieldOrDefault(selection); if (currentSelection != null) { result = MergeSelection(result.Item2, currentSelection); } } } return(result.Item2 != null); }
protected virtual bool EnterSelection(IFieldSelection selection) { Fields.Push(selection.Field); if (selection.Field.Type.IsLeafType() || (selection.Field.Type.IsListType() && selection.Field.Type.ElementType().IsLeafType())) { if (EnterLeaf(selection)) { LeaveLeaf(selection); } } else if (selection.Field.Type.IsListType() || selection.Field.Type.ToClrType() == typeof(IConnection) || (selection.Field.Member is PropertyInfo propertyInfo && IsListType(propertyInfo.PropertyType))) { if (EnterList(selection)) { LeaveList(selection); } }
public Expression HandleLeave( SelectionVisitorContext context, IFieldSelection selection, Expression expression) { ObjectField field = context.FieldSelection.Field; if (field.ContextData.ContainsKey(_contextDataKey) && field.Member is PropertyInfo propertyInfo) { Type elementType = GetInnerListType(propertyInfo.PropertyType); return(Expression.Call( typeof(Enumerable), "Take", new[] { elementType }, expression, Expression.Constant(_take))); } return(expression); }
protected override void LeaveObject(IFieldSelection selection) { if (selection.Field.Member is PropertyInfo) { Expression memberInit = Closures.Pop().CreateMemberInit(); Closures.Peek().Projections[selection.Field.Name] = Expression.Bind(selection.Field.Member, memberInit); base.LeaveObject(selection); } else { throw new QueryException( ErrorBuilder.New() .SetMessage( string.Format( "UseSelection is in a invalid state. Field {0}" + " should never have been visited!", selection.Field.Name)) .Build()); } }
public Expression HandleLeave( SelectionVisitorContext context, IFieldSelection selection, Expression expression) { if (context.TryGetValueNode("where", out IValueNode filter) && selection.Field.Arguments["where"].Type is InputObjectType iot && iot is IFilterInputType fit) { var visitor = new QueryableFilterVisitor( iot, fit.EntityType, context.Conversion); filter.Accept(visitor); return(Expression.Call( typeof(Enumerable), "Where", new[] { fit.EntityType }, expression, visitor.CreateFilter())); } return(expression); }
/// <summary> /// Adds the argument to specified <see cref="IFieldSelection"/>. /// </summary> /// <param name="field">The <see cref="IFieldSelection"/> to which the argument is added.</param> /// <param name="argument">The argument.</param> /// <returns>The <see cref="IFieldSelection"/>.</returns> public static IFieldSelection AddArgument(this IFieldSelection field, NamedValueToken argument) { Guard.ArgumentNotNull(field, nameof(field)); field.Arguments[argument.Name] = argument; return(field); }
public PreProcessingSelection(ObjectType objectType, IFieldSelection selectionField) { GraphQLObjectType = objectType ?? throw new ArgumentNullException(nameof(objectType)); GraphQLFieldSelection = selectionField ?? throw new ArgumentNullException(nameof(selectionField)); ClassMemberInfo = selectionField.Field?.Member; }