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());
            }
        }
示例#3
0
 /// <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));
 }
示例#4
0
        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));
 }
示例#7
0
        private IFieldSelection GetOffsetBasedPagingFieldOrDefault(IFieldSelection selection)
        {
            if (selection.Field.Name == "items")
            {
                return(selection);
            }

            return(null);
        }
示例#8
0
        /// <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));
        }
示例#9
0
        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);
        }
示例#13
0
        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.");
            }
        }
示例#15
0
        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);
        }
示例#17
0
        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);
        }
示例#19
0
        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);
        }
示例#20
0
        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());
            }
        }
示例#22
0
        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);
        }
示例#23
0
        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);
        }
示例#24
0
        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);
        }
示例#25
0
 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);
         }
     }
示例#26
0
        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());
            }
        }
示例#28
0
        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);
 }
示例#30
0
 public PreProcessingSelection(ObjectType objectType, IFieldSelection selectionField)
 {
     GraphQLObjectType     = objectType ?? throw new ArgumentNullException(nameof(objectType));
     GraphQLFieldSelection = selectionField ?? throw new ArgumentNullException(nameof(selectionField));
     ClassMemberInfo       = selectionField.Field?.Member;
 }