private static void ProcessProperties(IComplexGraphType graphType, IEnumerable <PropertyInfo> properties, bool isInputType = false)
        {
            foreach (var property in properties.OrderBy(p => p.Name))
            {
                bool isNotNull = TypeHelper.IsNotNull(property);

                var propertyGraphType = TypeHelper.GetGraphType(property);
                if (propertyGraphType != null)
                {
                    propertyGraphType = GraphTypeConverter.ConvertTypeToGraphType(propertyGraphType, isNotNull, isInputType);
                    propertyGraphType = EnsureList(property.PropertyType, propertyGraphType);
                }
                else
                {
                    propertyGraphType = GraphTypeConverter.ConvertTypeToGraphType(property.PropertyType, isNotNull, isInputType);
                }

                var name  = StringHelper.GraphName(property.Name);
                var field = graphType.AddField(new FieldType {
                    Type        = propertyGraphType,
                    Name        = name,
                    Description = TypeHelper.GetDescription(property)
                });

                field.DefaultValue      = TypeHelper.GetDefaultValue(property);
                field.DeprecationReason = TypeHelper.GetDeprecationReason(property);
            }
        }
    public static bool TryGetComplexGraph(this FieldType fieldType, out IComplexGraphType complexGraph)
    {
        var orAdd = GetOrAdd(fieldType);

        complexGraph = orAdd.ComplexGraphType;
        return(complexGraph != null);
    }
        public static FieldType Query <Controller>(this IComplexGraphType graphType, Type returnGraphType, Expression <Func <Controller, object> > methodCall)
        {
            var fieldType = ExpressionToFieldTypeGenerator.GenerateFieldType(graphType, methodCall, returnGraphType: returnGraphType);

            graphType.AddField(fieldType);
            return(fieldType);
        }
        public static FieldType QueryAsync <Controller>(this IComplexGraphType graphType, string name, Expression <Func <Controller, Task> > methodCall)
        {
            var fieldType = ExpressionToFieldTypeGenerator.GenerateAsyncFieldType(graphType, methodCall, name);

            graphType.AddField(fieldType);
            return(fieldType);
        }
 private void DeriveFields(GraphTypeInfo typeInfo, IComplexGraphType graphType)
 {
     foreach (var field in typeInfo.Fields.Select(DeriveField))
     {
         graphType.AddField(field);
     }
 }
        private static void ProcessFields(IComplexGraphType graphType, IEnumerable <FieldInfo> fields, bool isInputType = false)
        {
            foreach (var field in fields.OrderBy(f => f.Name))
            {
                bool isNotNull = TypeHelper.IsNotNull(field);

                var fieldGraphType = TypeHelper.GetGraphType(field);
                if (fieldGraphType != null)
                {
                    fieldGraphType = GraphTypeConverter.ConvertTypeToGraphType(fieldGraphType, isNotNull, isInputType);
                    fieldGraphType = EnsureList(field.FieldType, fieldGraphType);
                }
                else
                {
                    fieldGraphType = GraphTypeConverter.ConvertTypeToGraphType(field.FieldType, isNotNull, isInputType);
                }

                var addedField = graphType.AddField(new FieldType {
                    Type = fieldGraphType,
                    Name = StringHelper.GraphName(field.Name)
                });

                addedField.DeprecationReason = TypeHelper.GetDeprecationReason(field);
            }
        }
Beispiel #7
0
        public static void ApplyProperties <TModelType>(this IComplexGraphType instance)
        {
            var type = typeof(TModelType);

            foreach (var prop in type.GetProperties(BindingFlags.Public | BindingFlags.IgnoreCase | BindingFlags.Instance))
            {
                var fieldAttr = prop.GetCustomAttribute <GraphQLFieldAttribute>();
                if (fieldAttr == null)
                {
                    continue;
                }

                try
                {
                    instance.AddField(new FieldType
                    {
                        Name        = fieldAttr.Name ?? prop.Name.FirstCharacterToLower(),
                        Type        = fieldAttr.ReturnType ?? prop.PropertyType.ToGraphType(),
                        Resolver    = new PropertyResolver(prop),
                        Description = fieldAttr.Description
                    });
                }
                catch (ArgumentOutOfRangeException exception)
                {
                    throw new NotSupportedException(
                              $"Unable to register field for property {prop.Name}",
                              exception);
                }
            }
        }
Beispiel #8
0
            static ContentFieldData ToFieldData(IDictionary <string, object> source, IComplexGraphType type)
            {
                var result = new ContentFieldData();

                foreach (var field in type.Fields)
                {
                    if (source.TryGetValue(field.Name, out var value))
                    {
                        if (value is IEnumerable <object> list && field.ResolvedType.Flatten() is IComplexGraphType nestedType)
                        {
                            var array = new JsonArray(list.Count());

                            foreach (var item in list)
                            {
                                if (item is JsonObject nested)
                                {
                                    array.Add(nested);
                                }
                            }

                            result[field.SourceName()] = array;
                        }
                        else
                        {
                            result[field.SourceName()] = JsonGraphType.ParseJson(value);
                        }
                    }
                }

                return(result);
            }
Beispiel #9
0
        internal static IFilter ResolveFilter <TParentType>(
            this IComplexGraphType filterType,
            KeyValuePair <string, object> value,
            ResolveFieldContext <TParentType> context)
        {
            var path  = (context.Path ?? new[] { "filter" }).Concat(new[] { value.Key });
            var field = filterType.Fields.First(x => x.Name == value.Key);

            return((IFilter)field.Resolver.Resolve(
                       new ResolveFieldContext
            {
                FieldName = field.Name,
                FieldAst = new Field(null, new NameNode(field.Name)),
                FieldDefinition = field,
                ParentType = context.ParentType,
                Source = value.Value,
                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 = path,
            }
                       ));
        }
        internal static IFilter ResolveFilter(
            this IComplexGraphType filterType,
            KeyValuePair <string, object> value,
            IObjectGraphType parentType,
            ExecutionContext executionContext)
        {
            var field = filterType.Fields.First(x => x.Name == value.Key);

            return((IFilter)field.Resolver.Resolve(
                       new ResolveFieldContext
            {
                FieldName = field.Name,
                FieldAst = new Field(null, new NameNode(field.Name)),
                FieldDefinition = field,
                ParentType = parentType,
                Source = value.Value,
                Schema = executionContext.Schema,
                Document = executionContext.Document,
                Fragments = executionContext.Fragments,
                RootValue = executionContext.RootValue,
                UserContext = executionContext.UserContext,
                Operation = executionContext.Operation,
                Variables = executionContext.Variables,
                CancellationToken = executionContext.CancellationToken,
                Metrics = executionContext.Metrics,
                Errors = executionContext.Errors,
            }
                       ));
        }
Beispiel #11
0
        private void AddAssetsQueries(IComplexGraphType assetType)
        {
            AddField(new FieldType
            {
                Name         = "queryAssets",
                Arguments    = CreateAssetQueryArguments(),
                ResolvedType = new ListGraphType(new NonNullGraphType(assetType)),
                Resolver     = ResolveAsync((c, e) =>
                {
                    var assetQuery = BuildODataQuery(c);

                    return(e.QueryAssetsAsync(assetQuery));
                }),
                Description = "Get assets."
            });

            AddField(new FieldType
            {
                Name         = "queryAssetsWithTotal",
                Arguments    = CreateAssetQueryArguments(),
                ResolvedType = new AssetsResultGraphType(assetType),
                Resolver     = ResolveAsync((c, e) =>
                {
                    var assetQuery = BuildODataQuery(c);

                    return(e.QueryAssetsAsync(assetQuery));
                }),
                Description = "Get assets and total count."
            });
        }
        private void AddAssetsQueries(IComplexGraphType assetType)
        {
            AddField(new FieldType
            {
                Name         = "queryAssets",
                Arguments    = CreateAssetQueryArguments(),
                ResolvedType = new ListGraphType(new NonNullGraphType(assetType)),
                Resolver     = ResolveAsync((c, e) =>
                {
                    var argTake  = c.GetArgument("take", 20);
                    var argSkip  = c.GetArgument("skip", 0);
                    var argQuery = c.GetArgument("search", string.Empty);

                    return(e.QueryAssetsAsync(argQuery, argSkip, argTake));
                }),
                Description = "Get assets."
            });

            AddField(new FieldType
            {
                Name         = "queryAssetsWithTotal",
                Arguments    = CreateAssetQueryArguments(),
                ResolvedType = new AssetsResultGraphType(assetType),
                Resolver     = ResolveAsync((c, e) =>
                {
                    var argTake  = c.GetArgument("take", 20);
                    var argSkip  = c.GetArgument("skip", 0);
                    var argQuery = c.GetArgument("search", string.Empty);

                    return(e.QueryAssetsAsync(argQuery, argSkip, argTake));
                }),
                Description = "Get assets and total count."
            });
        }
Beispiel #13
0
        public FieldType AddUnionQueryField <TUnion, TSource>(
            IComplexGraphType graph,
            string name,
            Func <ResolveEfFieldContext <TDbContext, TSource>, Task <IDictionary <Type, IQueryable <object> > > >?resolveAsync = null,
            IEnumerable <QueryArgument>?arguments = null,
            string?description = null) where TUnion : UnionGraphType
        {
            Guard.AgainstNull(nameof(graph), graph);
            var field = BuildUnionQueryField <TUnion, TSource>(name, resolveAsync, arguments, description);

            return(graph.AddField(field));
        }
        void AddQueryableConnection <TSource, TGraph, TReturn>(
            IComplexGraphType graph,
            string name,
            Func <ResolveEfFieldContext <TDbContext, TSource>, IQueryable <TReturn> >?resolve,
            IEnumerable <QueryArgument>?arguments,
            int pageSize,
            string?description)
            where TGraph : IGraphType
            where TReturn : class
        {
            var builder = ConnectionBuilder.Create <TGraph, TSource>();

            builder.Name(name);
            if (description != null)
            {
                builder.Description(description);
            }
            builder.PageSize(pageSize).Bidirectional();

            if (resolve != null)
            {
                builder.Resolve(
                    context =>
                {
                    var efFieldContext = BuildContext(context);
                    var query          = resolve(efFieldContext);
                    if (disableTracking)
                    {
                        query = query.AsNoTracking();
                    }
                    query     = includeAppender.AddIncludes(query, context);
                    var names = GetKeyNames <TReturn>();
                    query     = query.ApplyGraphQlArguments(context, names, true);
                    return(query
                           .ApplyConnectionContext(
                               context.First,
                               context.After,
                               context.Last,
                               context.Before,
                               context,
                               context.CancellationToken,
                               efFieldContext.Filters));
                });
            }

            // TODO: works around https://github.com/graphql-dotnet/graphql-dotnet/pull/2581/
            builder.FieldType.Type = typeof(NonNullGraphType <ConnectionType <TGraph, EdgeType <TGraph> > >);
            var field = graph.AddField(builder.FieldType);

            var hasId = keyNames.ContainsKey(typeof(TReturn));

            field.AddWhereArgument(hasId, arguments);
        }
Beispiel #15
0
        private void HandleField(IComplexGraphType parentType, FieldType field, TypeCollectionContext context, bool applyNameConverter)
        {
            // applyNameConverter will be false while processing the three root introspection query fields: __schema, __type, and __typename
            //
            // During processing of those three root fields, the NameConverter will be set to the schema's selected NameConverter,
            //   and the field names must not be processed by the NameConverter
            //
            // For other introspection types and fields, the NameConverter will be set to CamelCaseNameConverter at the time this
            //   code executes, and applyNameConverter will be true
            //
            // For any other fields, the NameConverter will be set to the schema's selected NameConverter at the time this code
            //   executes, and applyNameConverter will be true

            if (applyNameConverter)
            {
                field.Name = NameConverter.NameForField(field.Name, parentType);
                NameValidator.ValidateName(field.Name);
            }

            if (field.ResolvedType == null)
            {
                AddTypeIfNotRegistered(field.Type, context);
                field.ResolvedType = BuildNamedType(field.Type, context.ResolveType);
            }
            else
            {
                AddTypeIfNotRegistered(field.ResolvedType, context);
            }

            if (field.Arguments == null)
            {
                return;
            }

            foreach (var arg in field.Arguments)
            {
                if (applyNameConverter)
                {
                    arg.Name = NameConverter.NameForArgument(arg.Name, parentType, field);
                    NameValidator.ValidateName(arg.Name, "argument");
                }

                if (arg.ResolvedType != null)
                {
                    AddTypeIfNotRegistered(arg.ResolvedType, context);
                    continue;
                }

                AddTypeIfNotRegistered(arg.Type, context);
                arg.ResolvedType = BuildNamedType(arg.Type, context.ResolveType);
            }
        }
        public string PrintFields(IComplexGraphType type)
        {
            var fields = type?.Fields
                         .Select(x =>
                                 new
            {
                x.Name,
                Type = ResolveName(Schema.FindType(x.Type)),
                Args = PrintArgs(x)
            }).ToList();

            return(string.Join(Environment.NewLine, fields?.Select(f => "  {0}{1}: {2}".ToFormat(f.Name, f.Args, f.Type))));
        }
Beispiel #17
0
        public FieldType GenerateFieldType <Controller, ReturnType>(IComplexGraphType graphType, Expression <Func <Controller, ReturnType> > methodCall, string name = null, Type returnGraphType = null)
        {
            var fieldInfo = expressionToFieldInfoTransformer.FromExpression(methodCall, typeof(Controller));
            var fieldType = fieldInfoToFieldTypeTransformer.TransformToFieldType(fieldInfo, returnGraphType);

            if (!(name is null))
            {
                fieldType.Name = name;
            }
            fieldType.Resolver = fieldInfoResolver.GenerateFieldResolver(graphType, fieldInfo);

            return(fieldType);
        }
    public FieldType AddQueryField <TReturn>(
        IComplexGraphType graph,
        string name,
        Func <ResolveEfFieldContext <TDbContext, object>, IQueryable <TReturn> >?resolve = null,
        Type?graphType = null,
        IEnumerable <QueryArgument>?arguments = null,
        string?description = null)
        where TReturn : class
    {
        var field = BuildQueryField(graphType, name, resolve, arguments, description);

        return(graph.AddField(field));
    }
Beispiel #19
0
 /// <summary>
 /// Adds the specified fields to the specified graph.
 /// Skips null fields.
 /// </summary>
 public static void AddFields(IComplexGraphType graphType, IEnumerable <FieldType?>?fieldTypes)
 {
     if (fieldTypes != null)
     {
         foreach (var fieldType in fieldTypes)
         {
             if (fieldType != null)
             {
                 graphType.AddField(fieldType);
             }
         }
     }
 }
Beispiel #20
0
        public FieldType AddQueryField <TSource, TReturn>(
            IComplexGraphType graph,
            string name,
            Func <ResolveEfFieldContext <TDbContext, TSource>, IQueryable <TReturn> >?resolve = null,
            Type?itemGraphType = null,
            IEnumerable <QueryArgument>?arguments = null,
            string?description = null)
            where TReturn : class
        {
            Guard.AgainstNull(nameof(graph), graph);
            var field = BuildQueryField(itemGraphType, name, resolve, arguments, description);

            return(graph.AddField(field));
        }
 public DelegateToFieldRule(
     IComplexGraphType graphType,
     string fieldName,
     string delegateFieldName,
     Func <TModel, TDelegateID> idGetter)
 {
     ResolvedType = graphType.GetField(fieldName).ResolvedType as IComplexGraphType;
     if (ResolvedType == null)
     {
         throw new Exception($"ResolvedType of an object authorized by {GetType().Name} must be an IComplexGraphType");
     }
     DelegateFieldName = delegateFieldName;
     IDGetter          = idGetter;
 }
        public FieldType AddQueryField <TReturn>(
            IComplexGraphType graph,
            string name,
            Func <ResolveEfFieldContext <TDbContext, object>, Task <IQueryable <TReturn> > >?resolveAsync = null,
            Type?graphType = null,
            IEnumerable <QueryArgument>?arguments = null,
            string?description           = null,
            bool disableDefaultArguments = false)
            where TReturn : class
        {
            Guard.AgainstNull(nameof(graph), graph);
            var field = BuildQueryField(graphType, name, resolveAsync, arguments, description, disableDefaultArguments);

            return(graph.AddField(field));
        }
Beispiel #23
0
        public FieldType AddSingleField <TSource, TReturn>(
            IComplexGraphType graph,
            string name,
            Func <ResolveEfFieldContext <TDbContext, TSource>, IQueryable <TReturn> > resolve,
            Func <ResolveEfFieldContext <TDbContext, TSource>, TReturn, Task>?mutate = null,
            Type?graphType = null,
            IEnumerable <QueryArgument>?arguments = null,
            bool nullable      = false,
            string?description = null)
            where TReturn : class
        {
            var field = BuildSingleField(name, resolve, mutate, arguments, graphType, nullable, description);

            return(graph.AddField(field));
        }
        public void AddQueryConnectionField <TSource, TReturn>(
            IComplexGraphType graph,
            string name,
            Func <ResolveEfFieldContext <TDbContext, TSource>, IQueryable <TReturn> >?resolve = null,
            Type?itemGraphType = null,
            IEnumerable <QueryArgument>?arguments = null,
            int pageSize       = 10,
            string?description = null)
            where TReturn : class
        {
            itemGraphType ??= GraphTypeFinder.FindGraphType <TReturn>();
            var addConnectionT = addQueryableConnection.MakeGenericMethod(typeof(TSource), itemGraphType, typeof(TReturn));

            addConnectionT.Invoke(this, new object?[] { graph, name, resolve, arguments, pageSize, description });
        }
Beispiel #25
0
        /// <summary>
        /// Checks input type received via introspection query for correctness
        /// </summary>
        /// <param name="graphType">
        /// The type to check
        /// </param>
        /// <param name="checkedInputTypes">
        /// The types already checked (to limit the recursion)
        /// </param>
        /// <returns>
        /// The list of found errors
        /// </returns>
        private static IEnumerable <string> CheckInputGraphType(
            IComplexGraphType graphType,
            ICollection <string> checkedInputTypes)
        {
            if (checkedInputTypes.Contains(graphType.Name))
            {
                yield break;
            }

            checkedInputTypes.Add(graphType.Name);

            if (graphType.Fields == null || !graphType.Fields.Any())
            {
                yield return($"Input type {graphType.Name} has no fields");

                yield break;
            }

            foreach (var field in graphType.Fields)
            {
                var fieldResolvedType = GetResolvedType(field.ResolvedType);
                if (fieldResolvedType == null)
                {
                    yield return($"Input type {graphType.Name} has field {field.Name} of unknown type");

                    continue;
                }

                if (!(fieldResolvedType is ScalarGraphType) && !(fieldResolvedType is IInputGraphType) &&
                    !(fieldResolvedType is InputObjectGraphType))
                {
                    yield return
                        ($"Field {field.Name} of type {graphType.Name} "
                         + $"has argument {field.Name} has invalid type {fieldResolvedType.Name}");

                    continue;
                }

                var complexGraphType = fieldResolvedType as IComplexGraphType;
                if (complexGraphType != null)
                {
                    foreach (var error in CheckInputGraphType(complexGraphType, checkedInputTypes))
                    {
                        yield return(error);
                    }
                }
            }
        }
Beispiel #26
0
        public virtual string PrintFields(IComplexGraphType type)
        {
            var fields = type?.Fields
                         .Select(x =>
                                 new
            {
                x.Name,
                Type        = ResolveName(x.ResolvedType),
                Args        = PrintArgs(x),
                Description = Options.IncludeDescriptions ? PrintDescription(x.Description, "  ") : string.Empty,
                Deprecation = Options.IncludeDeprecationReasons ? PrintDeprecation(x.DeprecationReason) : string.Empty,
            }).ToList();

            return(string.Join(Environment.NewLine, fields?.Select(
                                   f => "{3}  {0}{1}: {2}{4}".ToFormat(f.Name, f.Args, f.Type, f.Description, f.Deprecation))));
        }
Beispiel #27
0
        public void AddQueryConnectionField <TSource, TReturn>(
            IComplexGraphType graph,
            string name,
            Func <ResolveEfFieldContext <TDbContext, TSource>, IQueryable <TReturn> >?resolve = null,
            Type?itemGraphType = null,
            IEnumerable <QueryArgument>?arguments = null,
            int pageSize       = 10,
            string?description = null)
            where TReturn : class
        {
            Guard.AgainstNull(nameof(graph), graph);

            var connection = BuildQueryConnectionField(name, resolve, pageSize, itemGraphType, description);

            var field = graph.AddField(connection.FieldType);

            field.AddWhereArgument(arguments);
        }
        public override string PrintFields(IComplexGraphType type)
        {
            var fields = type?.Fields
                         .Where(x => !IsFederatedType(x.ResolvedType.GetNamedType().Name))
                         .Select(x =>
                                 new
            {
                x.Name,
                Type                = ResolveName(x.ResolvedType),
                Args                = PrintArgs(x),
                Description         = Options.IncludeDescriptions ? PrintDescription(x.Description, "  ") : string.Empty,
                Deprecation         = Options.IncludeDeprecationReasons ? PrintDeprecation(x.DeprecationReason) : string.Empty,
                FederatedDirectives = PrintFederatedDirectivesFromAst(x)
            }).ToList();

            return(string.Join(Environment.NewLine, fields?.Select(
                                   f => "{3}  {0}{1}: {2}{4}{5}".ToFormat(f.Name, f.Args, f.Type, f.Description, f.Deprecation, f.FederatedDirectives))));
        }
        public static void Field(
            this IComplexGraphType obj,
            string name,
            IGraphType type,
            string description       = null,
            QueryArguments arguments = null,
            Func <IResolveFieldContext, object> resolve = null)
        {
            var field = new FieldType
            {
                Name         = name,
                Description  = description,
                Arguments    = arguments,
                ResolvedType = type,
                Resolver     = resolve != null ? new FuncFieldResolver <object>(resolve) : null
            };

            obj.AddField(field);
        }
        private static void ProcessMethods(IComplexGraphType graphType, Type type, IEnumerable <MethodInfo> methods)
        {
            if (!typeof(GraphType).IsAssignableFrom(type) &&
                !type.IsDefined(typeof(GraphTypeAttribute)))
            {
                return;
            }
            foreach (var method in methods.OrderBy(m => m.Name))
            {
                if (IsSpecialMethod(method))
                {
                    continue;
                }

                bool isNotNull       = TypeHelper.IsNotNull(method);
                var  returnGraphType = TypeHelper.GetGraphType(method);
                var  methodGraphType = returnGraphType;
                if (methodGraphType != null)
                {
                    methodGraphType = GraphTypeConverter.ConvertTypeToGraphType(methodGraphType, isNotNull);
                    methodGraphType = EnsureList(method.ReturnType, methodGraphType);
                }
                else
                {
                    methodGraphType = GraphTypeConverter.ConvertTypeToGraphType(method.ReturnType, isNotNull);
                }

                var arguments =
                    new QueryArguments(
                        method.GetParameters()
                        .Where(p => p.ParameterType != typeof(ResolveFieldContext))
                        .Select(CreateArgument));

                // todo: need to fix method execution - not called currently so lower priority
                graphType.AddField(new FieldType {
                    Type              = methodGraphType,
                    Name              = StringHelper.GraphName(method.Name),
                    Arguments         = arguments,
                    DeprecationReason = TypeHelper.GetDeprecationReason(method),
                    //Resolver = new AsyncFuncFieldResolver(()=>ResolveField(context, field))
                });
            }
        }