public TypeNameMetaFieldType()
 {
     Name = "__typename";
     Type = typeof(NonNullGraphType<StringGraphType>);
     Description = "The name of the current Object type at runtime.";
     Resolver = new FuncFieldResolver<object>((context) => context.ParentType.Name);
 }
 public TypeMetaFieldType()
 {
     Name = "__type";
     Type = typeof(__Type);
     Description = "Request the type information of a single type.";
     Arguments = new QueryArguments(
         new QueryArgument<NonNullGraphType<StringGraphType>>
         {
             Name = "name"
         });
     Resolver = new FuncFieldResolver<object>(context => context.Schema.FindType((string) context.Arguments["name"]));
 }
示例#3
0
        public void SqlJunction_WhenFieldResolverIsNotNull_DoesntSetResolver()
        {
            var resolver  = new FuncFieldResolver <string>(_ => "");
            var fieldType = new FieldType
            {
                Name     = "name",
                Resolver = resolver
            };

            fieldType.SqlJunction("", (join, arguments, context, node) => { },
                                  (join, arguments, context, node) => { });

            fieldType.Resolver.Should().Be(resolver);
        }
示例#4
0
        public void Initialize(IGraphModel model, ISchemaEntity schema)
        {
            var schemaType = schema.TypeName();
            var schemaName = schema.DisplayName();

            Name = $"{schemaType}DataDto";

            foreach (var field in schema.SchemaDef.Fields.Where(x => !x.IsHidden))
            {
                var fieldInfo = model.GetGraphType(field);

                if (fieldInfo.ResolveType != null)
                {
                    var fieldName = field.RawProperties.Label.WithFallback(field.Name);

                    var fieldGraphType = new ObjectGraphType
                    {
                        Name = $"{schemaType}Data{field.Name.ToPascalCase()}Dto"
                    };

                    var partition = model.ResolvePartition(field.Partitioning);

                    foreach (var partitionItem in partition)
                    {
                        fieldGraphType.AddField(new FieldType
                        {
                            Name         = partitionItem.Key,
                            Resolver     = fieldInfo.Resolver,
                            ResolvedType = fieldInfo.ResolveType,
                            Description  = field.RawProperties.Hints
                        });
                    }

                    fieldGraphType.Description = $"The structure of the {fieldName} of a {schemaName} content type.";

                    var fieldResolver = new FuncFieldResolver <NamedContentData, ContentFieldData>(c => c.Source.GetOrDefault(field.Name));

                    AddField(new FieldType
                    {
                        Name         = field.Name.ToCamelCase(),
                        Resolver     = fieldResolver,
                        ResolvedType = fieldGraphType,
                        Description  = $"The {fieldName} field."
                    });
                }
            }

            Description = $"The structure of a {schemaName} content type.";
        }
        public ChatSubscriptions(IChat chat)
        {
            _chat = chat;
            AddField(new EventStreamFieldType
            {
                Name       = "messageAdded",
                Type       = typeof(MessageType),
                Resolver   = new FuncFieldResolver <Message>(ResolveMessage),
                Subscriber = new EventStreamResolver <Message>(Subscribe)
            });

            AddField(new EventStreamFieldType
            {
                Name       = "contentAdded",
                Type       = typeof(MessageType),
                Resolver   = new FuncFieldResolver <Message>(ResolveMessage),
                Subscriber = new EventStreamResolver <Message>(Subscribe)
            });

            AddField(new EventStreamFieldType
            {
                Name      = "messageAddedByUser",
                Arguments = new QueryArguments(
                    new QueryArgument <NonNullGraphType <StringGraphType> > {
                    Name = "id"
                }
                    ),
                Type       = typeof(MessageType),
                Resolver   = new FuncFieldResolver <Message>(ResolveMessage),
                Subscriber = new EventStreamResolver <Message>(SubscribeById)
            });

            AddField(new EventStreamFieldType
            {
                Name       = "userJoined",
                Type       = typeof(MessageFromType),
                Resolver   = new FuncFieldResolver <MessageFrom>(context => context.Source as MessageFrom),
                Subscriber = new EventStreamResolver <MessageFrom>(context => _chat.UserJoined())
            });


            AddField(new EventStreamFieldType
            {
                Name       = "failImmediately",
                Type       = typeof(MessageType),
                Resolver   = new FuncFieldResolver <Message>(ResolveMessage),
                Subscriber = new EventStreamResolver <Message>(context => throw new NotSupportedException("this is supposed to fail"))
            });
示例#6
0
        public ContentDataGraphType(Schema schema, IGraphQLContext context)
        {
            var schemaName = schema.Properties.Label.WithFallback(schema.Name);

            Name = $"{schema.Name.ToPascalCase()}DataDto";

            foreach (var field in schema.Fields.Where(x => !x.IsHidden))
            {
                var fieldInfo = context.GetGraphType(field);

                if (fieldInfo.ResolveType != null)
                {
                    var fieldName = field.RawProperties.Label.WithFallback(field.Name);

                    var fieldGraphType = new ObjectGraphType
                    {
                        Name = $"{schema.Name.ToPascalCase()}Data{field.Name.ToPascalCase()}Dto"
                    };

                    var partition = context.ResolvePartition(field.Paritioning);

                    foreach (var partitionItem in partition)
                    {
                        fieldGraphType.AddField(new FieldType
                        {
                            Name         = partitionItem.Key,
                            Resolver     = fieldInfo.Resolver,
                            ResolvedType = fieldInfo.ResolveType,
                            Description  = field.RawProperties.Hints
                        });
                    }

                    fieldGraphType.Description = $"The structure of the {fieldName} of a {schemaName} content type.";

                    var fieldResolver = new FuncFieldResolver <NamedContentData, ContentFieldData>(c => c.Source.GetOrDefault(field.Name));

                    AddField(new FieldType
                    {
                        Name         = field.Name.ToCamelCase(),
                        Resolver     = fieldResolver,
                        ResolvedType = fieldGraphType
                    });
                }
            }

            Description = $"The structure of a {schemaName} content type.";
        }
示例#7
0
 public ProfileLocationSubscriptions(IEntityObjectEventService eventService)
 {
     _eventService = eventService;
     _eventService.EntityObjectEvent += EventService_OnEntityObjectEvent;
     #region Group
     AddField(new EventStreamFieldType
     {
         Name        = "group_OnInsert",
         Description = "Raises when a new Group has been inserted",
         Type        = typeof(GroupType),
         Resolver    = new FuncFieldResolver <Group>(context => context.Source as Group),
         Subscriber  = new EventStreamResolver <Group>(context => _groupInsertObservable)
     });
     AddField(new EventStreamFieldType
     {
         Name        = "group_OnChange",
         Description = "Raises when a any update/change to an existing Group",
         Type        = typeof(GroupType),
         Resolver    = new FuncFieldResolver <Group>(context => context.Source as Group),
         Subscriber  = new EventStreamResolver <Group>(context => _groupChangeObservable)
     });
     AddField(new EventStreamFieldType
     {
         Name        = "group_OnUpdate",
         Description = "Raises when specified ID Group has been updated",
         Arguments   = new QueryArguments(new QueryArgument <NonNullGraphType <IntGraphType> >()
         {
             Name = "Id", Description = "Key of object to receive updates from"
         }),
         Type       = typeof(GroupType),
         Resolver   = new FuncFieldResolver <Group>(context => context.Source as Group),
         Subscriber = new EventStreamResolver <Group>(context =>
         {
             var id = context.GetArgument <int>("id");
             if (_groupUpdateObservables.TryGetValue(id, out var observable))
             {
                 return(observable);
             }
             observable = new EntityObservable <Group>(() => _groupUpdateObservables.Remove(id));
             _groupUpdateObservables[id] = observable;
             return(observable);
         })
     });
        public TypeNameMetaFieldType()
        {
            Name        = "__typename";
            Type        = typeof(NonNullGraphType <StringGraphType>);
            Description = "The name of the current Object type at runtime.";
            Resolver    = new FuncFieldResolver <object>(context => context.ParentType.Name);

            // TODO: kapiris additions - need PR!

            /*
             * Resolver = new FuncFieldResolver<object>((context) =>
             * {
             *  if (context.ParentType.IsCompositeType()
             *      && context.ParentType.GetType().GetGenericTypeDefinition() == typeof(ObjectGraphType<>))
             *  {
             *      return $"ObjectGraphType<{context.ParentType.GetType().GetGenericArguments()[0]?.Name}>";
             *  }
             *
             *  return context.ParentType.Name;
             * });
             */
        }
示例#9
0
        public void Does_Not_Share_Incomplete_Tasks_Typed()
        {
            IResolveFieldContext <int?> rfc1 = null;
            IResolveFieldContext <int?> rfc2 = null;
            var ffr1 = new FuncFieldResolver <int?, Task <string> >(async context => {
                rfc1 = context;
                await Task.Delay(100);
                return("ok");
            });
            var ffr2 = new FuncFieldResolver <int?, Task <string> >(async context => {
                rfc2 = context;
                await Task.Delay(100);
                return("ok");
            });

            ffr1.Resolve(_context);
            ffr2.Resolve(_context);
            rfc1.ShouldNotBeNull();
            rfc1.ShouldNotBeSameAs(_context);
            rfc2.ShouldNotBeNull();
            rfc2.ShouldNotBeSameAs(_context);
            rfc1.ShouldNotBe(rfc2);
        }
        public void Shares_Complete_Untyped()
        {
            IResolveFieldContext <int?> rfc1 = null;
            IResolveFieldContext <int?> rfc2 = null;
            var ffr1 = new FuncFieldResolver <int?, object>(context =>
            {
                rfc1 = context;
                return("ok");
            });
            var ffr2 = new FuncFieldResolver <int?, object>(context =>
            {
                rfc2 = context;
                return("ok");
            });

            ffr1.Resolve(_context);
            ffr2.Resolve(_context);
            rfc1.ShouldNotBeNull();
            rfc1.ShouldNotBeSameAs(_context);
            rfc2.ShouldNotBeNull();
            rfc2.ShouldNotBeSameAs(_context);
            rfc1.ShouldBe(rfc2);
        }
        public void Does_Not_Share_Dataloader_Typed()
        {
            IResolveFieldContext <int?> rfc1 = null;
            IResolveFieldContext <int?> rfc2 = null;
            var ffr1 = new FuncFieldResolver <int?, IDataLoaderResult>(context =>
            {
                rfc1 = context;
                return(_okDataLoader);
            });
            var ffr2 = new FuncFieldResolver <int?, IDataLoaderResult>(context =>
            {
                rfc2 = context;
                return(_okDataLoader);
            });

            ffr1.Resolve(_context);
            ffr2.Resolve(_context);
            rfc1.ShouldNotBeNull();
            rfc1.ShouldNotBeSameAs(_context);
            rfc2.ShouldNotBeNull();
            rfc2.ShouldNotBeSameAs(_context);
            rfc1.ShouldNotBe(rfc2);
        }
        public void Does_Not_Share_Dataloader_Tasks_Untyped_Derived()
        {
            IResolveFieldContext <int?> rfc1 = null;
            IResolveFieldContext <int?> rfc2 = null;
            var ffr1 = new FuncFieldResolver <int?, object>(context =>
            {
                rfc1 = context;
                return(Task.FromResult(_okDataLoader));
            });
            var ffr2 = new FuncFieldResolver <int?, object>(context =>
            {
                rfc2 = context;
                return(Task.FromResult(_okDataLoader));
            });

            ffr1.Resolve(_context);
            ffr2.Resolve(_context);
            rfc1.ShouldNotBeNull();
            rfc1.ShouldNotBeSameAs(_context);
            rfc2.ShouldNotBeNull();
            rfc2.ShouldNotBeSameAs(_context);
            rfc1.ShouldNotBe(rfc2);
        }
        public void Shares_Complete_Tasks_Typed()
        {
            IResolveFieldContext <int?> rfc1 = null;
            IResolveFieldContext <int?> rfc2 = null;
            var ffr1 = new FuncFieldResolver <int?, Task <string> >(context =>
            {
                rfc1 = context;
                return(Task.FromResult("ok"));
            });
            var ffr2 = new FuncFieldResolver <int?, Task <string> >(context =>
            {
                rfc2 = context;
                return(Task.FromResult("ok"));
            });

            ffr1.Resolve(_context);
            ffr2.Resolve(_context);
            rfc1.ShouldNotBeNull();
            rfc1.ShouldNotBeSameAs(_context);
            rfc2.ShouldNotBeNull();
            rfc2.ShouldNotBeSameAs(_context);
            rfc1.ShouldBe(rfc2);
        }
        public void Does_Not_Share_Failed_Tasks_Untyped_1()
        {
            IResolveFieldContext <int?> rfc1 = null;
            IResolveFieldContext <int?> rfc2 = null;
            var ffr1 = new FuncFieldResolver <int?, object>(context =>
            {
                rfc1 = context;
                return(Task.FromException <string>(new Exception()));
            });
            var ffr2 = new FuncFieldResolver <int?, object>(context =>
            {
                rfc2 = context;
                return(Task.FromResult("ok"));
            });

            ffr1.Resolve(_context);
            ffr2.Resolve(_context);
            rfc1.ShouldNotBeNull();
            rfc1.ShouldNotBeSameAs(_context);
            rfc2.ShouldNotBeNull();
            rfc2.ShouldNotBeSameAs(_context);
            rfc1.ShouldNotBe(rfc2);
        }
        public void Does_Not_Share_Enumerable_Tasks_Untyped()
        {
            IResolveFieldContext <int?> rfc1 = null;
            IResolveFieldContext <int?> rfc2 = null;
            var ffr1 = new FuncFieldResolver <int?, object>(context =>
            {
                rfc1 = context;
                return(Task.FromResult <IEnumerable <int> >(new[] { 1, 2 }));
            });
            var ffr2 = new FuncFieldResolver <int?, object>(context =>
            {
                rfc2 = context;
                return(Task.FromResult <IEnumerable <int> >(new[] { 1, 2 }));
            });

            ffr1.Resolve(_context);
            ffr2.Resolve(_context);
            rfc1.ShouldNotBeNull();
            rfc1.ShouldNotBeSameAs(_context);
            rfc2.ShouldNotBeNull();
            rfc2.ShouldNotBeSameAs(_context);
            rfc1.ShouldNotBe(rfc2);
        }
    public async Task Does_Not_Share_Dataloader_Typed()
    {
        IResolveFieldContext <int?> rfc1 = null;
        IResolveFieldContext <int?> rfc2 = null;
        var ffr1 = new FuncFieldResolver <int?, IDataLoaderResult>(context =>
        {
            rfc1 = context;
            return(_okDataLoader);
        });
        var ffr2 = new FuncFieldResolver <int?, IDataLoaderResult>(context =>
        {
            rfc2 = context;
            return(_okDataLoader);
        });
        await ffr1.ResolveAsync(_context).ConfigureAwait(false);

        await ffr2.ResolveAsync(_context).ConfigureAwait(false);

        rfc1.ShouldNotBeNull();
        rfc1.ShouldNotBeSameAs(_context);
        rfc2.ShouldNotBeNull();
        rfc2.ShouldNotBeSameAs(_context);
        rfc1.ShouldNotBe(rfc2);
    }
    public async Task Does_Not_Share_Enumerable_Untyped()
    {
        IResolveFieldContext <int?> rfc1 = null;
        IResolveFieldContext <int?> rfc2 = null;
        var ffr1 = new FuncFieldResolver <int?, object>(context =>
        {
            rfc1 = context;
            return(new[] { 1, 2 });
        });
        var ffr2 = new FuncFieldResolver <int?, object>(context =>
        {
            rfc2 = context;
            return(new[] { 1, 2 });
        });
        await ffr1.ResolveAsync(_context).ConfigureAwait(false);

        await ffr2.ResolveAsync(_context).ConfigureAwait(false);

        rfc1.ShouldNotBeNull();
        rfc1.ShouldNotBeSameAs(_context);
        rfc2.ShouldNotBeNull();
        rfc2.ShouldNotBeSameAs(_context);
        rfc1.ShouldNotBe(rfc2);
    }
    public async Task Shares_Complete_Untyped()
    {
        IResolveFieldContext <int?> rfc1 = null;
        IResolveFieldContext <int?> rfc2 = null;
        var ffr1 = new FuncFieldResolver <int?, object>(context =>
        {
            rfc1 = context;
            return("ok");
        });
        var ffr2 = new FuncFieldResolver <int?, object>(context =>
        {
            rfc2 = context;
            return("ok");
        });
        await ffr1.ResolveAsync(_context).ConfigureAwait(false);

        await ffr2.ResolveAsync(_context).ConfigureAwait(false);

        rfc1.ShouldNotBeNull();
        rfc1.ShouldNotBeSameAs(_context);
        rfc2.ShouldNotBeNull();
        rfc2.ShouldNotBeSameAs(_context);
        rfc1.ShouldBe(rfc2);
    }
示例#19
0
        public void Initialize(IGraphModel model, ISchemaEntity schema)
        {
            var schemaType = schema.TypeName();
            var schemaName = schema.DisplayName();

            Name = $"{schemaType}DataDto";

            foreach (var field in schema.SchemaDef.Fields.ForApi())
            {
                var(resolvedType, valueResolver) = model.GetGraphType(schema, field);

                if (valueResolver != null)
                {
                    var fieldType = field.TypeName();
                    var fieldName = field.DisplayName();

                    var fieldGraphType = new ObjectGraphType
                    {
                        Name = $"{schemaType}Data{fieldType}Dto"
                    };

                    var partition = model.ResolvePartition(field.Partitioning);

                    foreach (var partitionItem in partition)
                    {
                        var key = partitionItem.Key;

                        var partitionResolver = new FuncFieldResolver <object>(c =>
                        {
                            if (((ContentFieldData)c.Source).TryGetValue(key, out var value))
                            {
                                return(valueResolver(value, c));
                            }
                            else
                            {
                                return(null);
                            }
                        });

                        fieldGraphType.AddField(new FieldType
                        {
                            Name         = key.EscapePartition(),
                            Resolver     = partitionResolver,
                            ResolvedType = resolvedType,
                            Description  = field.RawProperties.Hints
                        });
                    }

                    fieldGraphType.Description = $"The structure of the {fieldName} field of the {schemaName} content type.";

                    var fieldResolver = new FuncFieldResolver <NamedContentData, IReadOnlyDictionary <string, IJsonValue> >(c =>
                    {
                        return(c.Source.GetOrDefault(field.Name));
                    });

                    AddField(new FieldType
                    {
                        Name         = field.Name.ToCamelCase(),
                        Resolver     = fieldResolver,
                        ResolvedType = fieldGraphType,
                        Description  = $"The {fieldName} field."
                    });
                }
            }

            Description = $"The structure of the {schemaName} content type.";
        }
        public DynamicMutationType(IGraphQlTypePool graphTypePool, IEnumerable <Type> types)
        {
            Name        = "Mutations";
            Description = "Contains the mutation of the graphql api";

            foreach (var type in types)
            {
                if (!type.IsClass || type.IsInterface)
                {
                    throw new ArgumentException("Invalid subscription type");
                }

                // work with the methods
                var methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly)
                              .Where(x => x.GetAttribute <IgnoreAttribute>() == null);

                foreach (var method in methods)
                {
                    if (method.Name == nameof(GraphNodeType <object> .OnCreateAsync) ||
                        method.IsSpecialName)
                    {
                        continue;
                    }

                    var descriptionAttr = method.GetAttribute <DescriptionAttribute>();
                    var fieldNameAttr   = method.GetAttribute <NameAttribute>();

                    IGraphType     graphType;
                    IFieldResolver resolver;
                    if (method.ReturnType.IsGenericType && method.ReturnType.GetGenericTypeDefinition() == typeof(Task <>))
                    {
                        var awaitableReturnType = method.ReturnType.GetGenericArguments()[0];
                        graphType = graphTypePool.GetGraphType(awaitableReturnType);
                        resolver  = new AsyncFieldResolver <object>(async c =>
                        {
                            var task = GraphQlHelpers.ExecuteResolverFunction(method, c, type, true);
                            await((Task)task);

                            var resultProp = task.GetType().GetProperty(nameof(Task <object> .Result));
                            var result     = resultProp.GetValue(task);

                            return(result);
                        });
                    }
                    else
                    {
                        graphType = graphTypePool.GetGraphType(method.ReturnType);
                        resolver  = new FuncFieldResolver <object>(c => GraphQlHelpers.ExecuteResolverFunction(method, c, type, true));
                    }

                    var isNonNull = method.GetAttribute <NonNullAttribute>() != null;

                    // create field
                    var field = new FieldType()
                    {
                        Arguments    = GraphQlHelpers.GetArguments(graphTypePool, method),
                        Name         = fieldNameAttr == null ? method.Name : fieldNameAttr.Name,
                        Description  = descriptionAttr?.Description ?? DocXmlHelper.DocReader.GetMemberComments(method).Summary,
                        ResolvedType = isNonNull ? new NonNullGraphType(graphType) : graphType,
                        Resolver     = resolver
                    };

                    // add the .net type of this field in the metadata
                    field.Metadata["type"] = method;

                    var metadatas = Attribute.GetCustomAttributes(type, typeof(MetadataAttribute));
                    foreach (MetadataAttribute metadata in metadatas)
                    {
                        Metadata[metadata.Key] = metadata.Value;
                    }

                    AddField(field);
                }
            }
        }
示例#21
0
        public DynamicGraphType(IGraphQlTypePool graphTypePool, Type type, bool isRoot = false)
        {
            if (!type.IsClass || type.IsInterface)
            {
                throw new ArgumentException("Invalid object type");
            }

            // get the name
            var nameAttr = type.GetAttribute <NameAttribute>();
            var descAttr = type.GetAttribute <DescriptionAttribute>();

            // set type name and description
            Name        = nameAttr?.Name ?? type.Name;
            Description = descAttr?.Description ?? DocXmlHelper.DocReader.GetTypeComments(type).Summary;

            // set the type metadata
            Metadata["type"] = type;

            {
                // sets the custom metadatas
                var metadatas = Attribute.GetCustomAttributes(type, typeof(MetadataAttribute));
                foreach (MetadataAttribute metadata in metadatas)
                {
                    Metadata[metadata.Key] = metadata.Value;
                }
            }

            // Check for interfaces
            var interfaces = type.GetNotDerivedInterfaces();

            // Add all the interface that this implement
            foreach (var intrfce in interfaces)
            {
                AddResolvedInterface(graphTypePool.GetGraphType(intrfce) as IInterfaceGraphType);
            }

            // Implementing isTypeOf in the case this type implement an interface
            IsTypeOf = obj => obj.GetType() == type;

            // Generate fields -----------------------------------------------
            // start with the properties
            var properties = type
                             // Get all properties with getters
                             .GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.SetProperty | BindingFlags.GetProperty)
                             // ignore the ones that have the ignore attribute
                             .Where(x => x.GetAttribute <IgnoreAttribute>() == null);

            foreach (var property in properties)
            {
                var graphType       = graphTypePool.GetGraphType(property.PropertyType);
                var descriptionAttr = property.GetAttribute <DescriptionAttribute>();
                var fieldNameAttr   = property.GetAttribute <NameAttribute>();
                var isNonNull       = property.GetAttribute <NonNullAttribute>() != null;

                // create field
                var field = new FieldType()
                {
                    Name         = fieldNameAttr == null ? property.Name : fieldNameAttr.Name,
                    Description  = descriptionAttr?.Description ?? DocXmlHelper.DocReader.GetMemberComments(property).Summary,
                    ResolvedType = isNonNull ? new NonNullGraphType(graphType) : graphType,
                    Resolver     = new FuncFieldResolver <object>(c => GraphQlHelpers.GetFinalValue(property.GetValue(GraphQlHelpers.GetSourceInstance(c, type, isRoot)))),
                };

                // add the .net type of this field in the metadata
                field.Metadata["type"] = property;

                var metadatas = Attribute.GetCustomAttributes(type, typeof(MetadataAttribute));
                foreach (MetadataAttribute metadata in metadatas)
                {
                    Metadata[metadata.Key] = metadata.Value;
                }

                AddField(field);
            }

            // work with the methods
            var methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly)
                          .Where(x => x.GetAttribute <IgnoreAttribute>() == null);

            // for each method public
            foreach (var method in methods)
            {
                if (method.Name == nameof(GraphNodeType <object> .OnCreateAsync) ||
                    method.IsSpecialName)
                {
                    continue;
                }

                var descriptionAttr = method.GetAttribute <DescriptionAttribute>();
                var fieldNameAttr   = method.GetAttribute <NameAttribute>();

                IGraphType     graphType;
                IFieldResolver resolver;
                if (method.ReturnType.IsGenericType && method.ReturnType.GetGenericTypeDefinition() == typeof(Task <>))
                {
                    var awaitableReturnType = method.ReturnType.GetGenericArguments()[0];
                    graphType = graphTypePool.GetGraphType(awaitableReturnType);
                    resolver  = new AsyncFieldResolver <object>(async c =>
                    {
                        var task = GraphQlHelpers.ExecuteResolverFunction(method, c, type, isRoot);
                        await((Task)task);

                        var resultProp = task.GetType().GetProperty(nameof(Task <object> .Result));
                        var result     = resultProp.GetValue(task);

                        return(result);
                    });
                }
                else
                {
                    graphType = graphTypePool.GetGraphType(method.ReturnType);
                    resolver  = new FuncFieldResolver <object>(c => GraphQlHelpers.ExecuteResolverFunction(method, c, type, isRoot));
                }

                var isNonNull = method.GetAttribute <NonNullAttribute>() != null;

                // create field
                var field = new FieldType()
                {
                    Arguments    = GraphQlHelpers.GetArguments(graphTypePool, method),
                    Name         = fieldNameAttr == null ? method.Name : fieldNameAttr.Name,
                    Description  = descriptionAttr?.Description ?? DocXmlHelper.DocReader.GetMemberComments(method).Summary,
                    ResolvedType = isNonNull ? new NonNullGraphType(graphType) : graphType,
                    Resolver     = resolver
                };

                // add the .net type of this field in the metadata
                field.Metadata["type"] = method;

                var metadatas = Attribute.GetCustomAttributes(type, typeof(MetadataAttribute));
                foreach (MetadataAttribute metadata in metadatas)
                {
                    Metadata[metadata.Key] = metadata.Value;
                }

                AddField(field);
            }
        }
        public DynamicGraphType(IGraphQlTypePool graphTypePool, Type type)
        {
            //if (!typeof(GraphNodeType<>).IsAssignableFrom(type))
            //{
            //    throw new ArgumentException("The type is not of type GraphNodeType<>");
            //}

            // get the name
            var nameArgument = type.GetAttribute <TypeNameAttribute>();
            var name         = nameArgument == null ? type.Name : nameArgument.Name;

            // set type name
            Name = name;

            // Generate fields -----------------------------------------------
            // start with the properties
            var properties = type
                             // Get all properties with getters
                             .GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.SetProperty | BindingFlags.GetProperty)
                             // ignore the ones that have the ignore attribute
                             .Where(x => x.GetAttribute <IgnoreFieldAttribute>() == null);

            foreach (var property in properties)
            {
                var graphType       = graphTypePool.GetGraphType(property.PropertyType);
                var descriptionAttr = property.GetAttribute <FieldDescriptionAttribute>();
                var fieldNameAttr   = property.GetAttribute <FieldNameAttribute>();
                var isNonNull       = property.GetAttribute <NonNullFieldAttribute>() != null;

                // create field
                var field = new FieldType()
                {
                    Name         = fieldNameAttr == null ? property.Name : fieldNameAttr.Name,
                    Description  = descriptionAttr?.Description,
                    ResolvedType = isNonNull ? new NonNullGraphType(graphType) : graphType,
                    Resolver     = new FuncFieldResolver <object>(c => property.GetValue(c.Source))
                };

                AddField(field);
            }

            // work with the methods
            var methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly)
                          .Where(x => x.GetAttribute <IgnoreFieldAttribute>() == null);

            foreach (var method in methods)
            {
                if (method.Name == nameof(GraphNodeType <object> .OnCreateAsync) ||
                    method.IsSpecialName)
                {
                    continue;
                }

                var descriptionAttr = method.GetAttribute <FieldDescriptionAttribute>();
                var fieldNameAttr   = method.GetAttribute <FieldNameAttribute>();

                IGraphType     graphType;
                IFieldResolver resolver;
                if (method.IsGenericMethod && method.ReturnType.GetGenericTypeDefinition() == typeof(Task <>))
                {
                    var awaitableReturnType = method.ReturnType.GetGenericArguments()[0];
                    graphType = graphTypePool.GetGraphType(awaitableReturnType);
                    resolver  = new AsyncFieldResolver <object>(c =>
                    {
                        var task = ExecuteResolverFunction(method, c);
                        return(task as Task <object>);
                    });
                }
                else
                {
                    graphType = graphTypePool.GetGraphType(method.ReturnType);
                    resolver  = new FuncFieldResolver <object>(c => ExecuteResolverFunction(method, c));
                }

                var isNonNull = method.GetAttribute <NonNullFieldAttribute>() != null;

                // create field
                var field = new FieldType()
                {
                    Arguments    = GetArguments(graphTypePool, method),
                    Name         = fieldNameAttr == null ? method.Name : fieldNameAttr.Name,
                    Description  = descriptionAttr?.Description,
                    ResolvedType = isNonNull ? new NonNullGraphType(graphType) : graphType,
                    Resolver     = resolver
                };
            }
        }