Esempio n. 1
0
 internal static void Register <TProduct>(ComplexGraphType <TProduct> type, Func <IResolveFieldContext <TProduct>, Object> reviewResolver = null)
     where TProduct : IProduct
 {
     type.Field(p => p.Name).Description("The products name");
     type.Field(p => p.Id).Description("The products id").Type(new NonNullGraphType(new IdGraphType()));
     type.Field(p => p.Stock).Description("The number of products in stock");
     type.Field(p => p.Type).Description("The type of product");
     type.Field <ListGraphType <ReviewType> >("reviews", resolve: reviewResolver);
 }
Esempio n. 2
0
        public static void Add(IStatsProvider statsProvider, ComplexGraphType <object> type)
        {
            type.Field <ListGraphType <StatType> >("stats", arguments: new QueryArguments
            {
                new QueryArgument(typeof(StringGraphType))
                {
                    Name        = "team1",
                    Description = "Team 1"
                },

                new QueryArgument(typeof(StringGraphType))
                {
                    Name        = "team2",
                    Description = "Team 2"
                }
            },
                                                   resolve: context =>
            {
                var c     = context as ResolveFieldContext;
                var team1 = c.Arguments["team1"].ToString();
                var team2 = c.Arguments["team2"].ToString();

                return(statsProvider.GetStatsAsync(team1, team2).Result);
            });
        }
Esempio n. 3
0
        public static ComplexGraphType <IPublishedContent> AddUmbracoBuiltInProperties(this ComplexGraphType <IPublishedContent> graphType)
        {
            // TODO: set this field name as a reserved property alias
            graphType.Field <PublishedContentDataGraphType>("_contentData", "Built in published content data.", resolve: context => context.Source).SetDoctypeMetadata(graphType.GetMetadata <string>("documentTypeAlias"));

            return(graphType);
        }
        static void AddMember <TSource>(ComplexGraphType <TSource> graph, PropertyInfo property)
        {
            var(compile, propertyGraphType) = Compile <TSource>(property);
            var resolver     = new SimpleFieldResolver <TSource>(compile);
            var graphQlField = graph.Field(type: propertyGraphType, name: property.Name);

            graphQlField.Resolver = resolver;
        }
        public static void SetFields <TSourceType>(ComplexGraphType <TSourceType> type, IEnumerable <PropertyInfo> properties, GraphObjectTypeReflectionOptions <TSourceType> options)
        {
            // Default the options if we get a null passed in.
            if (options == null)
            {
                options = new GraphObjectTypeReflectionOptions <TSourceType>();
            }

            //type.Name = typeof(TSourceType).GraphQLName(); // Don't do this, it will then break with Input types.

            // Helper method that works out if
            bool isNullable(PropertyInfo propertyInfo)
            {
                if (!options.Nullable.HasValue)
                {
                    return(IsNullableProperty(propertyInfo));
                }

                if (options.NullableProperties?.Any(p => GetPropertyName(p) == propertyInfo.Name) == true)
                {
                    return(true);
                }

                if (options.NonNullableProperties?.Any(p => GetPropertyName(p) == propertyInfo.Name) == true)
                {
                    return(false);
                }

                return(options.Nullable.Value);
            }

            foreach (var propertyInfo in properties)
            {
                if (options.ExcludedProperties?.Any(p => GetPropertyName(p) == propertyInfo.Name) == true)
                {
                    continue;
                }

                if (options.SkipExisting)
                {
                    if (type.Fields.Any(p => p.Name == propertyInfo.Name))
                    {
                        continue;
                    }
                }

                type.Field(
                    type: propertyInfo.PropertyType.GetGraphTypeFromType(isNullable(propertyInfo)),
                    name: propertyInfo.Name,
                    description: propertyInfo.Description(),
                    deprecationReason: propertyInfo.ObsoleteMessage()
                    ).DefaultValue = (propertyInfo.GetCustomAttributes(typeof(DefaultValueAttribute), false).FirstOrDefault() as DefaultValueAttribute)?.Value;
            }
        }
Esempio n. 6
0
        public static GraphQL.Builders.FieldBuilder <object, IQueryable <TSource> > CustomField <TGraphType, TSource>(
            this ComplexGraphType <object> graphType,
            string name,
            System.Func <GraphQL.IResolveFieldContext <object>, IQueryable <TSource> > resolve)
            where TSource : class
        {
            var builder = graphType.Field <ObjectGraphType <IQueryable <TSource> >, IQueryable <TSource> >(name);

            builder.Resolve(resolve);
            return(builder);
        }
Esempio n. 7
0
        public static FieldType RemoteField <TSourceType>(this ComplexGraphType <TSourceType> self, IEnumerable <Type> types, string remoteMoniker, string typeName, string name, string description = null, QueryArguments arguments = null, Func <ResolveFieldContext <TSourceType>, object> resolve = null, string deprecationReason = null)
        {
            var type = types.FirstOrDefault(t => t.GetCustomAttributes(true).Any(a => a is RemoteLiteralGraphTypeMetadataAttribute metadata && metadata.RemoteMoniker == remoteMoniker && metadata.Name == typeName));

            if (type == null)
            {
                throw new ArgumentException($"Couldn't find a type in {nameof(types)} with remote '{remoteMoniker}' and name '{name}'");
            }

            return(self.Field(type, name, description, arguments, resolve, deprecationReason));
        }
Esempio n. 8
0
        public static FieldType AssociationField <TSourceType>(
            this ComplexGraphType <TSourceType> _this,
            IGraphTypesCache graphTypesCache, string name, IReadOnlyList <string> allowedTypes, string roleId, GraphDirections graphDirection)
        {
            var graphTypes = allowedTypes.Select(ckId => graphTypesCache.GetOrCreate(ckId));

            var unionType = new RtEntityAssociationType(
                $"{_this.Name}_{name}{CommonConstants.GraphQlUnionSuffix}",
                $"Association {roleId} ({graphDirection}) of entity type {_this.Name}", graphTypesCache, graphTypes, roleId, graphDirection);

            return(_this.Field(name, null, unionType, resolve: context => context.Source));
        }
        /// <summary>
        /// Adds a field that gets an entity by id.
        /// Example usage:
        /// <code>
        ///     this.AddSingleField<Order, NodeObjectType<Order>, IdGraphType>("id", context => {
        ///         var id = Guid.Parse(context.GetArgument<string>("id"));
        ///         var order = orderRepository.GetOrderById(id);
        ///         return order;
        ///     });
        /// </code>
        /// </summary>
        /// <typeparam name="TEntity">The type of the entity.</typeparam>
        /// <typeparam name="TEntityGraphType">The type of the entity's GraphQL type (i.e. NodeObjectType<Entity>)</typeparam>
        /// <typeparam name="TId">The type of the id field (i.e. IdGraphType or IntGraphType)</typeparam>
        /// <param name="type"></param>
        /// <param name="idName">The name of the id property.</param>
        /// <param name="resolve">The resolving function that returns a <see cref="TEntity"/>.</param>
        /// <param name="name">The name of the field.</param>
        public static FieldType AddSingleField <TEntity, TEntityGraphType, TId>(this ComplexGraphType <object> type, string idName, Func <ResolveFieldContext <object>, object> resolve, string name = null) where TEntity : class, new() where TEntityGraphType : ComplexGraphType <object>, IGraphType <TEntity> where TId : GraphType
        {
            // create name if non is given
            var lowerCaseName = name != null ? name : $"{typeof(TEntity).Name.ToFirstLower()}";

            var arguments = new QueryArguments(
                new QueryArgument <NonNullGraphType <TId> >
            {
                Name        = idName,
                Description = $"id of a {lowerCaseName}"
            });

            return(type.Field(typeof(TEntityGraphType).ConvertToVirtualType(), lowerCaseName, $"The {lowerCaseName}", arguments, resolve));
        }
Esempio n. 10
0
        public static void AddField(IContainer container, ComplexGraphType <Object> obj, Type type, PropertyInfo propertyInfo, MethodInfo methodInfo)
        {
            if (propertyInfo.PropertyType == typeof(IContainer))
            {
                return;
            }
            var fieldType        = propertyInfo.PropertyType;
            var fieldName        = StringExtensions.PascalCase(propertyInfo.Name);
            var fieldDescription = "";
            var authFieldName    = $"{type.FullName}.{propertyInfo.Name}";

            Func <ResolveFieldContext <object>, object> contextResolve;

            if (methodInfo != null)
            {
                // Custom mapping of property
                contextResolve = context =>
                {
                    AuthorizeProperty(container, authFieldName);
                    return(methodInfo.Invoke(obj, GetArgumentsForMethod(methodInfo, container, context)));
                };
            }
            else
            {
                // 1 to 1 mapping of property to source
                contextResolve = context =>
                {
                    AuthorizeProperty(container, authFieldName);
                    var properties = context.Source.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public);
                    var sourceProp = properties.FirstOrDefault(p => p.Name == propertyInfo.Name);
                    if (sourceProp == null)
                    {
                        throw new ArgumentException($"No matching source property found for GraphObject. Type: {type.Name} Property: {propertyInfo.Name}");
                    }
                    return(sourceProp.GetValue(context.Source));
                };
            }
            var graphType = TypeLoader.GetGraphType(fieldType);
            var nonNull   = Enumerable.Any(propertyInfo.CustomAttributes, a => a.AttributeType == typeof(RequiredAttribute));

            if (nonNull)
            {
                graphType = typeof(NonNullGraphType <>).MakeGenericType(graphType);
            }
            obj.Field(graphType, fieldName, fieldDescription, null, contextResolve);
            container.GetInstance <AuthorizationMap>().AddAuthorization(type, propertyInfo);
        }
Esempio n. 11
0
        public static ComplexGraphType <IPublishedContent> AddUmbracoContentPropeties(
            this ComplexGraphType <IPublishedContent> graphType,
            IContentTypeComposition contentType,
            PublishedItemType publishedItemType)
        {
            var publishedContentType = PublishedContentType.Get(publishedItemType, contentType.Alias);

            foreach (var property in contentType.CompositionPropertyTypes)
            {
                //TODO: black/whitelist properties
                if (property.PropertyEditorAlias == Constants.PropertyEditors.ListViewAlias ||
                    property.PropertyEditorAlias == Constants.PropertyEditors.FolderBrowserAlias ||
                    property.Alias.StartsWith("umbracoMember"))
                {
                    continue;
                }

                var publishedPropertyType = publishedContentType.GetPropertyType(property.Alias);

                var resolver = GraphQLValueResolversResolver.Current.FindResolver(publishedPropertyType)
                               ?? new DefaultValueResolver();

                var propertyGraphType = resolver.GetGraphQLType(publishedPropertyType);

                if (property.Mandatory)
                {
                    propertyGraphType = typeof(NonNullGraphType <>).MakeGenericType(propertyGraphType);
                }

                graphType.Field(
                    propertyGraphType,
                    property.Alias.ToCamelCase(),
                    property.Description,
                    resolve: context =>
                {
                    var publishedProperty = context.Source.GetProperty(property.Alias);
                    return(publishedProperty == null
                            ? null
                            : resolver.Resolve(publishedPropertyType, publishedProperty.Value));
                }
                    ).SetPermissions(graphType);
            }

            return(graphType);
        }
Esempio n. 12
0
        public static void Add(ITeamsProvider teamsProvider, ComplexGraphType<object> type)
        {

            type.Field<ListGraphType<TeamType>>("teams",
             arguments: new QueryArguments
             {
                 new QueryArgument(typeof(StringGraphType))
                 {
                     Name = "search",
                     Description = "Search for teams",
                     DefaultValue = "*"

                 }
             },
            resolve: context =>
            {
                if (_teams == null) _teams = teamsProvider.GetTeamsAsync().Result;

                var search = (string)(context as ResolveFieldContext).Arguments["search"];

                return search == "*" ? _teams : _teams.Where(t => t.Name.ToLower().Contains(search.ToLower())).OrderBy(t => t.Name).ToList();
            });
        }
Esempio n. 13
0
        public static void AddFields <T>(ComplexGraphType <T> graph, bool skipMutableFields = false)
        {
            bool isInputType = graph is IInputObjectGraphType;

            foreach (var exposedPropery in typeof(T).GetProperties().Where(
                         p => Attribute.IsDefined(p, typeof(ApiAttribute))))
            {
                if (skipMutableFields)
                {
                    var mutable = (Attribute.GetCustomAttribute(exposedPropery, typeof(ApiAttribute)) as ApiAttribute).Mutable;

                    if (!mutable)
                    {
                        continue;
                    }
                }

                var underlyingType = exposedPropery.PropertyType;
                var isNullable     = Nullable.GetUnderlyingType(underlyingType) != null;

                if (isNullable)
                {
                    underlyingType = Nullable.GetUnderlyingType(exposedPropery.PropertyType);
                }

                var parameter        = Expression.Parameter(typeof(T), "type");
                var memberExpression = Expression.Property(parameter, exposedPropery.Name);
                var fieldExpression  = Expression.Lambda(memberExpression, parameter);

                if (underlyingType.IsEnum)
                {
                    RegisterEnum(underlyingType);
                }

                switch (underlyingType.Name)
                {
                case "String":
                    graph.Field((Expression <Func <T, string> >)fieldExpression, isNullable, typeof(StringGraphType));
                    break;

                case "Int32":
                    if (isNullable)
                    {
                        graph.Field((Expression <Func <T, int?> >)fieldExpression, isNullable, typeof(IntGraphType));
                    }
                    else
                    {
                        graph.Field((Expression <Func <T, int> >)fieldExpression, isNullable, typeof(IntGraphType));
                    }
                    break;

                case "Int64":
                case "Long":
                    if (isNullable)
                    {
                        graph.Field((Expression <Func <T, Int64?> >)fieldExpression, isNullable, typeof(LongGraphType));
                    }
                    else
                    {
                        graph.Field((Expression <Func <T, Int64> >)fieldExpression, isNullable, typeof(LongGraphType));
                    }
                    break;

                case "Double":
                    if (isNullable)
                    {
                        graph.Field((Expression <Func <T, double?> >)fieldExpression, isNullable, typeof(FloatGraphType));
                    }
                    else
                    {
                        graph.Field((Expression <Func <T, double> >)fieldExpression, isNullable, typeof(FloatGraphType));
                    }
                    break;

                case "DateTime":
                    if (isNullable)
                    {
                        graph.Field((Expression <Func <T, DateTime?> >)fieldExpression, isNullable, typeof(DateTimeGraphType));
                    }
                    else
                    {
                        graph.Field((Expression <Func <T, DateTime> >)fieldExpression, isNullable, typeof(DateTimeGraphType));
                    }
                    break;

                case "Boolean":
                    if (isNullable)
                    {
                        graph.Field((Expression <Func <T, bool?> >)fieldExpression, isNullable, typeof(BooleanGraphType));
                    }
                    else
                    {
                        graph.Field((Expression <Func <T, bool> >)fieldExpression, isNullable, typeof(BooleanGraphType));
                    }
                    break;

                case "List`1":
                    graph.Field((dynamic)fieldExpression, isNullable, GetListGraphType(underlyingType.GetGenericArguments()[0], isInputType));
                    break;

                default:
                    if (underlyingType.IsEnum)
                    {
                        graph.Field((dynamic)fieldExpression, isNullable, GetEnumType(underlyingType, isInputType));
                    }
                    else     // custom type
                    {
                        //graph.Field((dynamic)fieldExpression, isNullable, GetCustomGraphType(underlyingType, isInputType));
                        graph.Field((dynamic)fieldExpression, !isNullable,
                                    isInputType ? GetGraphInputType(exposedPropery.PropertyType, isInputType) :
                                    GetGraphType(exposedPropery.PropertyType, isInputType));
                    }
                    break;
                }
            }
        }
Esempio n. 14
0
        public static ComplexGraphType <IPublishedContent> AddContentDataProperties(this ComplexGraphType <IPublishedContent> graphType)
        {
            //TODO: black/whitelist properties
            graphType.Field <NonNullGraphType <DateGraphType> >("createDate", "Create date of the content.").SetPermissions(graphType, true);
            graphType.Field <NonNullGraphType <StringGraphType> >("creatorName", "Name of the content creator.").SetPermissions(graphType, true);
            graphType.Field <NonNullGraphType <StringGraphType> >("documentTypeAlias", "Document type alias of the content.").SetPermissions(graphType, true);
            graphType.Field <NonNullGraphType <IdGraphType> >("id", "Unique id of the content.").SetPermissions(graphType, true);
            graphType.Field <NonNullGraphType <IntGraphType> >("index", "Index of the content.", resolve: context => context.Source.GetIndex()).SetPermissions(graphType, true);
            graphType.Field <NonNullGraphType <IntGraphType> >("level", "Level of the content.").SetPermissions(graphType, true);
            graphType.Field <NonNullGraphType <BooleanGraphType> >("isFirst", "Is the content first in the list.", resolve: context => context.Source.IsFirst()).SetPermissions(graphType, true);
            graphType.Field <NonNullGraphType <BooleanGraphType> >("isLast", "Is the content last in the list.", resolve: context => context.Source.IsLast()).SetPermissions(graphType, true);
            graphType.Field <NonNullGraphType <BooleanGraphType> >("isVisible", "Is the content visible.", resolve: context => context.Source.IsVisible()).SetPermissions(graphType, true);
            graphType.Field <NonNullGraphType <StringGraphType> >("name", "Name of the content.").SetPermissions(graphType, true);
            graphType.Field <PublishedContentGraphType>("parent", "Parent of the content.").SetPermissions(graphType, true);
            graphType.Field <NonNullGraphType <IntGraphType> >("sortOrder", "SortOrder of the content.").SetPermissions(graphType, true);
            graphType.Field <NonNullGraphType <DateGraphType> >("updateDate", "Update date of the content.").SetPermissions(graphType, true);
            graphType.Field <NonNullGraphType <StringGraphType> >("url", "Url of the content.").SetPermissions(graphType, true);
            graphType.Field <NonNullGraphType <StringGraphType> >("urlAbsolute", "Absolute url of the content.", resolve: context => context.Source.UrlAbsolute()).SetPermissions(graphType, true);
            graphType.Field <NonNullGraphType <StringGraphType> >("writerName", "Name of the content writer.").SetPermissions(graphType, true);

            graphType.FilteredConnection <PublishedContentGraphType, IPublishedContent>()
            .Name("ancestors")
            .Description("Ancestors of the content.")
            .Argument <BooleanGraphType>("includeSelf", "include self in list")
            .Bidirectional()
            .Resolve(context =>
                     (context.GetArgument <bool?>("includeSelf") == true
                        ? context.Source.AncestorsOrSelf()
                        : context.Source.Ancestors()).Filter(context).ToConnection(context)
                     );

            graphType.FilteredConnection <PublishedContentGraphType, IPublishedContent>()
            .Name("siblings")
            .Description("Siblings of the content.")
            .Bidirectional()
            .Resolve(context => context.Source.Siblings().Filter(context).ToConnection(context));

            graphType.FilteredConnection <PublishedContentGraphType, IPublishedContent>()
            .Name("children")
            .Description("Children of the content.")
            .Bidirectional()
            .Resolve(context => context.Source.Children.Filter(context).ToConnection(context));

            return(graphType);
        }
        /// <summary>
        /// Adds a connection field.
        /// Example usage:
        /// <code>
        ///     this.AddConnectionField<Order, ObjectType<Order>>(context =>
        ///     {
        ///         return new Connection<Order>(orderRepository.GetOrders());
        ///     });
        /// </code>
        /// </summary>
        /// <typeparam name="T">The type of the model.</typeparam>
        /// <typeparam name="TT">The type of the GraphQL type (i.e. ObjectType<Model>)</typeparam>
        /// <param name="type"></param>
        /// <param name="resolve">The resolving func that retuns a connection model.</param>
        /// <param name="name">The name of the field.</param>
        public static FieldType AddConnectionField <T, TT>(this ComplexGraphType <object> type, Func <ResolveFieldContext <object>, object> resolve, string name = null, QueryArgument[] arguments = null) where T : class where TT : ComplexGraphType <object>, IGraphType <T>
        {
            // create name if non is given
            var lowerCaseName = name != null ? name : $"{typeof(T).Name.ToFirstLower()}s";

            // build argument list... first default ones
            var args = new QueryArguments(
                new QueryArgument <IdGraphType> {
                Name = "after"
            },
                new QueryArgument <IntGraphType> {
                Name = "first"
            },
                new QueryArgument <IdGraphType> {
                Name = "before"
            },
                new QueryArgument <IntGraphType> {
                Name = "last"
            });

            // construct order by type
            // create a class type "additionsType" and add a property for each item in "arguments"
            // if any custom arguments are set
            if (arguments != null)
            {
                var additionsType = TypeExtensions.CreateAdditionsTypeForType(typeof(T), arguments.Select(a => a.Name).ToArray());

                // create a type like OrderByType<T, additionsType> and use it below
                var orderByType = typeof(OrderByType <,>).MakeGenericType(new[] { typeof(T), additionsType });
                args.Add(new QueryArgument(orderByType)
                {
                    Name = "orderBy"
                });
            }
            else
            {
                args.Add(new QueryArgument <OrderByType <T> > {
                    Name = "orderBy"
                });
            }

            // ... then add an optional argument for each property of T
            var properties = typeof(T).GetExactProperies();

            foreach (var property in properties.Where(p => p.PropertyType.IsSimpleType()))
            {
                var propertyName = property.Name.ToFirstLower();
                args.Add(new QueryArgument(property.PropertyType.MapToGraphType())
                {
                    Name = propertyName
                });
            }

            // .. then add custom added arguments
            if (arguments != null)
            {
                args.AddRange(arguments);
            }

            // create field
            return(type.Field <ConnectionType <T, TT> >(lowerCaseName, $"The {lowerCaseName} connection.", args, resolve));
        }
        /// <summary>
        /// Creats a field from a given primitive property (like string, double, int etc.).
        /// </summary>
        /// <param name="type"></param>
        /// <param name="property">The property type to create a field for.</param>
        public static void CreateFieldFromPrimitiveProperty(this ComplexGraphType <object> type, PropertyInfo property)
        {
            var propertyName = property.Name.ToFirstLower();

            type.Field(property.PropertyType.MapToGraphType(), propertyName);
        }
        /// <summary>
        /// Adds a list field.
        /// Example usage:
        /// <code>
        ///     this.AddListfield<Order, ObjectType<Order>>()
        /// </code>
        /// </summary>
        /// <typeparam name="T">The type of the model.</typeparam>
        /// <typeparam name="TT">The type of the GraphQL type (i.e. ObjectType<Model>)</typeparam>
        /// <param name="type"></param>
        /// <param name="name">The name of the field. When no name is given, it is derived from the model type name.</param>
        public static FieldType AddListField <T, TT>(this ComplexGraphType <object> type, string name = null) where T : class where TT : ComplexGraphType <object>, IGraphType <T>
        {
            var lowerCaseName = name != null ? name : $"{typeof(T).Name.ToFirstLower()}s";

            return(type.Field <ListGraphType <TT> >(lowerCaseName));
        }
Esempio n. 18
0
 public static FieldBuilder <object, ModelType> IdField <GraphType, ModelType, ParamType>(this ComplexGraphType <object> parent, string fieldName, string paramName, string paramDescription) where GraphType : IGraphType
 {
     return(parent.Field <GraphType, ModelType>()
            .Name(fieldName)
            .Argument <ParamType>(paramName, paramDescription));
 }
        public static void AddField(IContainer container, ComplexGraphType <Object> obj, Type type, PropertyInfo propertyInfo, MethodInfo methodInfo)
        {
            if (propertyInfo.PropertyType == typeof(IContainer))
            {
                return;
            }
            var            fieldType        = propertyInfo.PropertyType;
            var            fieldName        = propertyInfo.Name.ToCamelCase();
            var            fieldDescription = "";
            var            authFieldName    = $"{type.FullName}.{propertyInfo.Name}";
            var            sourceType       = type.BaseType?.GenericTypeArguments.FirstOrDefault() ?? type;
            QueryArguments arguments        = null;

            Func <ResolveFieldContext <object>, object> contextResolve;

            if (methodInfo != null)
            {
                arguments = GetPropertyArguments(sourceType, methodInfo);
                // Custom mapping of property
                contextResolve = context =>
                {
                    AuthorizeProperty(container, authFieldName);
                    var sourceResolverInfo = container.GetInstance <ResolverInfoManager>().Create(context).First();
                    var output             = methodInfo.Invoke(obj, GetArgumentValues(methodInfo, container, context, sourceResolverInfo));
                    output = container.GetInstance <ApiSchema>().PropertyFilterManager.Filter(sourceResolverInfo, propertyInfo, authFieldName, output);
                    var baseType = TypeLoader.GetBaseType(output?.GetType(), out var isList);
                    if (output != null && !baseType.IsValueType)
                    {
                        container.GetInstance <ResolverInfoManager>().Create(context, output, sourceResolverInfo);
                    }
                    return(output);
                };
            }
            else
            {
                // 1 to 1 mapping of property to source
                contextResolve = context =>
                {
                    AuthorizeProperty(container, authFieldName);
                    var properties = context.Source.GetType().GetProperties(BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public);
                    var sourceProp = properties.FirstOrDefault(p => p.Name == propertyInfo.Name);
                    if (sourceProp == null)
                    {
                        throw new ArgumentException($"No matching source property found for GraphObject. Type: {type.Name} Property: {propertyInfo.Name}");
                    }
                    var output             = sourceProp.GetValue(context.Source);
                    var sourceResolverInfo = container.GetInstance <ResolverInfoManager>().Create(context).First();
                    output = container.GetInstance <ApiSchema>().PropertyFilterManager.Filter(sourceResolverInfo, propertyInfo, authFieldName, output);
                    var baseType = TypeLoader.GetBaseType(output?.GetType(), out var isList);
                    if (output != null && !baseType.IsValueType)
                    {
                        container.GetInstance <ResolverInfoManager>().Create(context, output, sourceResolverInfo);
                    }
                    return(output);
                };
            }
            var graphType = TypeLoader.GetGraphType(fieldType);
            var nonNull   = Enumerable.Any(propertyInfo.CustomAttributes, a => a.AttributeType == typeof(RequiredAttribute));

            if (nonNull)
            {
                graphType = typeof(NonNullGraphType <>).MakeGenericType(graphType);
            }
            var field = obj.Field(graphType, fieldName, fieldDescription, arguments, contextResolve);

            //field.ResolvedType = (IGraphType)Activator.CreateInstance(graphType);
            container.GetInstance <AuthorizationMap>().AddAuthorization(type, propertyInfo);
        }