public static QueryArguments GetArguments(IGraphQlTypePool graphTypePool, MethodInfo methodInfo)
        {
            var result     = new List <QueryArgument>();
            var parameters = methodInfo.GetParameters();

            foreach (var param in parameters)
            {
                if (param.ParameterType == typeof(CancellationToken))
                {
                    continue;
                }

                var argumentNameAttr        = param.GetAttribute <ArgumentNameAttribute>();
                var argumentDescriptionAttr = param.GetAttribute <ArgumentDescriptionAttribute>();
                var isNonNullType           = param.GetAttribute <NonNullArgumentAttribute>() != null;

                var name        = argumentNameAttr == null ? param.Name : argumentNameAttr.Name;
                var description = argumentDescriptionAttr == null ? "" : argumentDescriptionAttr.Description;

                var graphInputType = isNonNullType
                                            ? new NonNullGraphType(graphTypePool.GetInputType(param.ParameterType))
                                            : graphTypePool.GetInputType(param.ParameterType);

                var argument = new QueryArgument(graphInputType)
                {
                    Name         = name,
                    Description  = description,
                    DefaultValue = param.HasDefaultValue ? param.DefaultValue : null
                };

                result.Add(argument);
            }

            return(new QueryArguments(result));
        }
Beispiel #2
0
        public DynamicInterfaceType(IGraphQlTypePool graphTypePool, Type type)
        {
            if (!type.IsInterface)
            {
                throw new InvalidOperationException("The type has to be an interface");
            }

            // 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;

            var properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.SetProperty | BindingFlags.GetProperty);

            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;

                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
                };

                AddField(field);
            }
        }
Beispiel #3
0
        internal static QueryArguments GetArguments(IGraphQlTypePool graphTypePool, MethodInfo methodInfo)
        {
            var result     = new List <QueryArgument>();
            var parameters = methodInfo.GetParameters();

            foreach (var param in parameters)
            {
                if (param.ParameterType == typeof(CancellationToken))
                {
                    continue;
                }

                if (param.GetAttribute <InjectAttribute>() != null)
                {
                    continue;
                }

                var argumentNameAttr        = param.GetAttribute <NameAttribute>();
                var argumentDescriptionAttr = param.GetAttribute <DescriptionAttribute>();
                var isNonNullType           = param.GetAttribute <NonNullAttribute>() != null;

                var name        = argumentNameAttr == null ? param.Name : argumentNameAttr.Name;
                var description = argumentDescriptionAttr?.Description ??
                                  DocXmlHelper.DocReader.GetMethodComments(methodInfo)?.Parameters.FirstOrDefault(x => x.Name == param.Name).Text;

                var graphInputType = isNonNullType
                                            ? new NonNullGraphType(graphTypePool.GetInputType(param.ParameterType))
                                            : graphTypePool.GetInputType(param.ParameterType);

                var argument = new QueryArgument(graphInputType)
                {
                    Name         = name,
                    Description  = description,
                    DefaultValue = param.HasDefaultValue ? param.DefaultValue : null
                };

                result.Add(argument);
            }

            return(new QueryArguments(result));
        }
        public DynamicUnionGraphType(IGraphQlTypePool pool, Type type)
        {
            if (!typeof(IUnionGraphType).IsAssignableFrom(type))
            {
                throw new InvalidOperationException("Invalid Union type");
            }

            if (IsUnionType(type))
            {
                // Generate name
                var genericArguments = type.GetGenericArguments();
                Name = string.Join('_', genericArguments.Select(x => x.Name));
            }
            else
            {
                if (!IsUnionType(type.BaseType))
                {
                    throw new InvalidOperationException("Invalid Union type");
                }

                var nameAttr = type.GetAttribute <NameAttribute>();
                var descAttr = type.GetAttribute <DescriptionAttribute>();

                Name        = nameAttr?.Name ?? type.Name;
                Description = descAttr?.Description ?? DocXmlHelper.DocReader.GetTypeComments(type).Summary;

                type = type.BaseType;
            }

            {
                var genericArguments = type.GetGenericArguments();

                foreach (var genericArgument in genericArguments)
                {
                    AddPossibleType(pool.GetGraphType(genericArgument) as IObjectGraphType);
                }
            }
        }
        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);
                }
            }
        }
        public DynamicSubscriptionType(IGraphQlTypePool graphTypePool, IEnumerable <Type> types)
        {
            Name        = "Subscriptions";
            Description = "Contains the subscriptions of the graphql api";

            foreach (var type in types)
            {
                if (!type.IsClass || type.IsInterface)
                {
                    throw new ArgumentException("Invalid subscription 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 observableType = property.PropertyType.GetInterfacesIncludingType()
                                         .FirstOrDefault(x => x.IsGenericType && x.GetGenericTypeDefinition().Equals(typeof(IObservable <>)));

                    if (observableType == null)
                    {
                        throw new InvalidOperationException("Subscription property can only return or have type IObservable<>, derive from it or have the IgnoreAttribute");
                    }

                    var graphType       = graphTypePool.GetGraphType(observableType.GetGenericArguments()[0]);
                    var descriptionAttr = property.GetAttribute <DescriptionAttribute>();
                    var fieldNameAttr   = property.GetAttribute <NameAttribute>();
                    var isNonNull       = property.GetAttribute <NonNullAttribute>() != null;

                    var field = new EventStreamFieldType()
                    {
                        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>(ResolveObject),
                        Subscriber   = new EventStreamResolver <object>(c => Subscribe(c, property, type))
                    };

                    // 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);

                foreach (var method in methods)
                {
                    if (method.IsSpecialName)
                    {
                        continue;
                    }

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

                    IGraphType                graphType;
                    IEventStreamResolver      subscriber      = null;
                    IAsyncEventStreamResolver subscriberAsync = null;
                    if (method.ReturnType.IsGenericType && method.ReturnType.GetGenericTypeDefinition() == typeof(Task <>))
                    {
                        var observable = method.ReturnType.GetGenericArguments()[0];

                        var observableInterface = observable.GetInterfacesIncludingType()
                                                  .FirstOrDefault(x => x.IsGenericType && x.GetGenericTypeDefinition().Equals(typeof(IObservable <>)));

                        if (observableInterface == null)
                        {
                            throw new InvalidOperationException("Subscription property can only return or have type IObservable<>, derive from it or have the IgnoreAttribute");
                        }

                        var observableType = observableInterface.GetGenericArguments()[0];

                        graphType       = graphTypePool.GetGraphType(observableType);
                        subscriberAsync = new AsyncEventStreamResolver <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 as IObservable <object>);
                        });
                    }
                    else
                    {
                        var observable = method.ReturnType;

                        var observableInterface = observable.GetInterfacesIncludingType()
                                                  .FirstOrDefault(x => x.IsGenericType && x.GetGenericTypeDefinition().Equals(typeof(IObservable <>)));

                        var observableType = observableInterface.GetGenericArguments()[0];

                        graphType  = graphTypePool.GetGraphType(observableType);
                        subscriber = new EventStreamResolver <object>(c => GraphQlHelpers.ExecuteResolverFunction(method, c, type, true) as IObservable <object>);
                    }

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

                    // create field
                    var field = new EventStreamFieldType()
                    {
                        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        = new FuncFieldResolver <object>(ResolveObject),
                        Subscriber      = subscriber,
                        AsyncSubscriber = subscriberAsync
                    };

                    // 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);
                }
            }
        }
Beispiel #7
0
 public SchemaResolver(IAssemblyResolver assemblyResolver, IGraphQlTypePool graphQlTypePool)
 {
     _assemblyResolver = assemblyResolver;
     _graphQlTypePool  = graphQlTypePool;
 }
        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
                };
            }
        }
Beispiel #9
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);
            }
        }