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); }); }
public static void AddFields <TOutput>(IContainer container, ComplexGraphType <object> obj) where TOutput : class { var outputType = typeof(TOutput); var objectType = obj.GetType(); var filter = BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly; var methods = objectType.GetMethods(filter); var objectTypeProperties = objectType.GetProperties(filter); foreach (var propertyInfo in objectTypeProperties) { if (propertyInfo.GetMethod != null && propertyInfo.GetMethod.IsPublic) { AddField(container, obj, outputType, propertyInfo, methods.FirstOrDefault(m => m.Name == $"Get{propertyInfo.Name}")); } } foreach (var propertyInfo in outputType.GetProperties(filter)) { //Skip properties that are already defined in the object type if (objectTypeProperties.Any(p => p.Name == propertyInfo.Name)) { continue; } if (propertyInfo.GetMethod != null && propertyInfo.GetMethod.IsPublic) { AddField(container, obj, outputType, propertyInfo, methods.FirstOrDefault(m => m.Name == $"Get{propertyInfo.Name}")); } } }
public void ConfigureField(ComplexGraphType <TModel> graphType, GraphTypeCache cache, IServiceCollection services) { FieldType field; if (TryGetScalarGraphType(out var graphQlType)) { AuthResolver.ValidateGraphqlType(graphQlType, Property); field = new FieldType { Type = graphQlType, Name = Property.Name, Resolver = AuthResolver.GetResolver(services, NameFieldResolver.Instance) }; } else { if (ResolverConfiguration == null) { throw new UnableToResolveException(Property, typeof(TModel)); } field = ResolverConfiguration.ConfigureField(Property, cache, services); field.Resolver = AuthResolver.GetResolver(services, field.Resolver); } var descAttr = Property.GetCustomAttribute <DescriptionAttribute>(); field.Description = descAttr?.Description; var isOutputType = field.Type?.IsOutputType(); var isOutputGraphType = field.ResolvedType?.IsOutputType(); graphType.AddField(field); }
public void AddNavigationConnectionField <TSource, TReturn>( ComplexGraphType <TSource> graph, string name, Func <ResolveEfFieldContext <TDbContext, TSource>, IEnumerable <TReturn> >?resolve = null, Type?itemGraphType = null, IEnumerable <QueryArgument>?arguments = null, IEnumerable <string>?includeNames = null, int pageSize = 10, string?description = null) where TReturn : class { Guard.AgainstNull(nameof(graph), graph); Guard.AgainstNullWhiteSpace(nameof(name), name); Guard.AgainstNegative(nameof(pageSize), pageSize); itemGraphType ??= GraphTypeFinder.FindGraphType <TReturn>(); var fieldType = GetFieldType <TSource>(name, itemGraphType); var builder = ConnectionBuilder <TSource> .Create <FakeGraph>(name); if (description != null) { builder.Description(description); } builder.PageSize(pageSize).Bidirectional(); SetField(builder, fieldType); IncludeAppender.SetIncludeMetadata(builder.FieldType, name, includeNames); var hasId = keyNames.ContainsKey(typeof(TReturn)); if (resolve != null) { builder.ResolveAsync(async context => { var efFieldContext = BuildContext(context); var enumerable = resolve(efFieldContext); enumerable = enumerable.ApplyGraphQlArguments(hasId, context); enumerable = await efFieldContext.Filters.ApplyFilter(enumerable, context.UserContext); var page = enumerable.ToList(); return(ConnectionConverter.ApplyConnectionContext( page, context.First, context.After, context.Last, context.Before)); }); } var connection = builder; var field = graph.AddField(connection.FieldType); field.AddWhereArgument(hasId, arguments); }
internal static void AddAppliedDirectivesField <TSourceType>(this ComplexGraphType <TSourceType> type, string element) where TSourceType : IProvideMetadata { type.FieldAsync <NonNullGraphType <ListGraphType <NonNullGraphType <__AppliedDirective> > > >( name: "appliedDirectives", description: $"Directives applied to the {element}", resolve: async context => { if (context.Source !.HasAppliedDirectives()) { var appliedDirectives = context.Source.GetAppliedDirectives(); var result = context.ArrayPool.Rent <AppliedDirective>(appliedDirectives !.Count); int index = 0; foreach (var applied in appliedDirectives.List) { // return only registered directives allowed by filter var schemaDirective = context.Schema.Directives.Find(applied.Name); if (schemaDirective != null && await context.Schema.Filter.AllowDirective(schemaDirective)) { result[index++] = applied; } } return(result.Constrained(index)); } return(Array.Empty <AppliedDirective>()); }); }
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; }
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); }
public bool TryPrime <T>(ComplexGraphType <T> graphType) { if (_cache.ContainsKey(typeof(T))) { return(false); } _cache[typeof(T)] = graphType; return(true); }
/// <summary> /// Add all reflected properties as fields (unless they are specified in <paramref name="excludedProperties"/>. /// </summary> /// <typeparam name="TSourceType"></typeparam> /// <param name="type"></param> /// <param name="excludedProperties"></param> public static void AddAllPropertiesAsFields <TSourceType>(this ComplexGraphType <TSourceType> type, params Expression <Func <TSourceType, object> >[] excludedProperties) { GraphObjectTypeReflectionHelper.SetFields( type, GetRegisteredProperties(typeof(TSourceType)), new GraphObjectTypeReflectionOptions <TSourceType> { ExcludedProperties = excludedProperties, } ); }
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; } }
/// <summary> /// Adds a connection field. Shorthand for <see cref="AddConnectionField<TEntity, TEntityGraphType>" />. /// </summary> public static FieldType AddConnectionField(this ComplexGraphType <object> type, Type entityType, Func <ResolveFieldContext <object>, object> resolve, string name, params QueryArgument[] arguments) { // construct type parameters var entityGraphType = typeof(NodeObjectType <>).MakeGenericType(entityType).ConvertToVirtualType(); var method = typeof(ComplexGraphTypeExtensions).GetMethods().Where(m => m.Name == "AddConnectionField" && m.IsGenericMethod).First(); method = method.MakeGenericMethod(entityType, entityGraphType); // call like AddConnectionField<TEntity, TEntityGraphType>(...) return((FieldType)method.Invoke(null, new object[] { type, resolve, name, arguments })); }
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); }
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)); }
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. Shorthand for <see cref="AddSingleField<TEntity, TEntityGraphType, TId>" />. /// </summary> public static FieldType AddSingleField(this ComplexGraphType <object> type, Type entityType, Func <ResolveFieldContext <object>, object> resolve, string name) { // construct type parameters var entityGraphType = typeof(NodeObjectType <>).MakeGenericType(entityType).ConvertToVirtualType(); var idType = entityType.GetIdType().MapToGraphType(); var idName = entityType.GetIdPropertyName().ToFirstLower(); var method = typeof(ComplexGraphTypeExtensions).GetMethods().Where(m => m.Name == "AddSingleField" && m.IsGenericMethod && m.GetGenericArguments().Count() == 3).First(); method = method.MakeGenericMethod(entityType, entityGraphType, idType); // call like AddSingleField<TEntity, TEntityGraphType, TId>(...) return((FieldType)method.Invoke(null, new object[] { type, idName, resolve, name })); }
/// <summary> /// Add all reflected properties as fields (unless they are specified in <paramref name="excludedProperties"/>. /// /// Properties with names already registered will be excluded automatically, allowing you to do this after first specifying those fields you want to control manually. /// </summary> /// <typeparam name="TSourceType"></typeparam> /// <param name="type"></param> /// <param name="nullable"></param> /// <param name="excludedProperties"></param> public static void AddRemainingPropertiesAsFields <TSourceType>(this ComplexGraphType <TSourceType> type, bool?nullable = null, params Expression <Func <TSourceType, object> >[] excludedProperties) { GraphObjectTypeReflectionHelper.SetFields( type, GetRegisteredProperties(typeof(TSourceType)), new GraphObjectTypeReflectionOptions <TSourceType> { Nullable = nullable, ExcludedProperties = excludedProperties, SkipExisting = true, } ); }
void AddEnumerableConnection <TSource, TGraph, TReturn>( ComplexGraphType <TSource> graph, string name, Func <ResolveEfFieldContext <TDbContext, TSource>, IEnumerable <TReturn> >?resolve, int pageSize, string?description, IEnumerable <QueryArgument>?arguments, IEnumerable <string>?includeNames) where TGraph : IGraphType where TReturn : class { var builder = ConnectionBuilder.Create <TGraph, TSource>(); builder.Name(name); if (description is not null) { builder.Description(description); } builder.PageSize(pageSize).Bidirectional(); IncludeAppender.SetIncludeMetadata(builder.FieldType, name, includeNames); var hasId = keyNames.ContainsKey(typeof(TReturn)); if (resolve is not null) { builder.ResolveAsync(async context => { var efFieldContext = BuildContext(context); var enumerable = resolve(efFieldContext); enumerable = enumerable.ApplyGraphQlArguments(hasId, context); enumerable = await efFieldContext.Filters.ApplyFilter(enumerable, context.UserContext); var page = enumerable.ToList(); return(ConnectionConverter.ApplyConnectionContext( page, context.First, context.After, context.Last, context.Before)); }); } // TODO: works around https://github.com/graphql-dotnet/graphql-dotnet/pull/2581/ builder.FieldType.Type = typeof(NonNullGraphType <ConnectionType <TGraph, EdgeType <TGraph> > >); var field = graph.AddField(builder.FieldType); field.AddWhereArgument(hasId, arguments); }
/// <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)); }
static void MapProperties <TSource>(ComplexGraphType <TSource> graph, Type type, IReadOnlyList <string>?exclusions = null) { var publicProperties = type.GetPublicProperties() .OrderBy(x => x.Name); foreach (var property in publicProperties) { if (ShouldIgnore(graph, property.Name, property.PropertyType, exclusions)) { continue; } AddMember(graph, property); } }
public static void AutoMap <TSource>(this ComplexGraphType <TSource> graph, IReadOnlyList <string>?exclusions = null) { var type = typeof(TSource); try { MapProperties(graph, type, exclusions); } catch (GetGraphException exception) { throw new Exception($"Failed to map '{graph.GetType().Name}'. {exception.Message}"); } }
public static ConnectionBuilder <TSourceType> Connection <TNodeType, TGraphType, TSourceType>( this ComplexGraphType <TNodeType> _this, IGraphTypesCache entityDtoCache, TGraphType itemType, string prefixName) where TGraphType : IGraphType { var type = entityDtoCache.GetOrCreateConnection(itemType, prefixName); var connectionBuilder = ConnectionBuilder <TSourceType> .Create <TGraphType>( $"{prefixName}{CommonConstants.GraphQlConnectionSuffix}"); connectionBuilder.FieldType.ResolvedType = type; _this.AddField(connectionBuilder.FieldType); return(connectionBuilder); }
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); }
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); }
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); }
internal static FieldType FieldAsync <TSourceType>(this ComplexGraphType <TSourceType> _this, string name, string description = null, IGraphType graphType = null, QueryArguments arguments = null, Func <IResolveFieldContext <TSourceType>, Task <object> > resolve = null, string deprecationReason = null) { return(_this.AddField(new FieldType { Name = name, Description = description, DeprecationReason = deprecationReason, ResolvedType = graphType, Arguments = arguments, Resolver = resolve != null ? new AsyncFieldResolver <TSourceType, object>(resolve) : null })); }
public static void AddAllFields(IContainer container, ComplexGraphType <Object> obj, Type type, bool declaredPropertiesOnly) { var filter = BindingFlags.Instance | BindingFlags.Public; if (declaredPropertiesOnly) { filter = filter | BindingFlags.DeclaredOnly; } var methods = type.GetMethods(filter); foreach (var propertyInfo in type.GetProperties(filter)) { if (propertyInfo.GetMethod != null && propertyInfo.GetMethod.IsPublic) { AddField(container, obj, type, propertyInfo, methods.FirstOrDefault(m => m.Name == $"Get{propertyInfo.Name}")); } } }
public FieldType AddNavigationField <TSource, TReturn>( ComplexGraphType <TSource> graph, string name, Func <ResolveEfFieldContext <TDbContext, TSource>, TReturn?>?resolve = null, Type?graphType = null, IEnumerable <string>?includeNames = null, string?description = null) where TReturn : class { Guard.AgainstNull(nameof(graph), graph); Guard.AgainstNullWhiteSpace(nameof(name), name); graphType ??= GraphTypeFinder.FindGraphType <TReturn>(); FieldType field = new() { Name = name, Type = graphType, Description = description }; IncludeAppender.SetIncludeMetadata(field, name, includeNames); if (resolve != null) { field.Resolver = new AsyncFieldResolver <TSource, TReturn?>( async context => { var fieldContext = BuildContext(context); var result = resolve(fieldContext); if (await fieldContext.Filters.ShouldInclude(context.UserContext, result)) { return(result); } return(null); }); } return(graph.AddField(field)); } }
internal static void AutoMap <TDbContext, TSource>( ComplexGraphType <TSource> graph, IEfGraphQLService <TDbContext> graphService, IReadOnlyList <string>?exclusions = null) where TDbContext : DbContext { var type = typeof(TSource); try { MapNavigationProperties(graph, graphService, type, exclusions); MapProperties(graph, type, exclusions); } catch (GetGraphException exception) { throw new Exception($"Failed to map '{graph.GetType().Name}'. {exception.Message}"); } }
public void AddNavigationConnectionField <TSource, TReturn>( ComplexGraphType <TSource> graph, string name, Func <ResolveEfFieldContext <TDbContext, TSource>, IEnumerable <TReturn> >?resolve = null, Type?itemGraphType = null, IEnumerable <QueryArgument>?arguments = null, IEnumerable <string>?includeNames = null, int pageSize = 10, string?description = null) where TReturn : class { Guard.AgainstWhiteSpace(nameof(name), name); Guard.AgainstNegative(nameof(pageSize), pageSize); itemGraphType ??= GraphTypeFinder.FindGraphType <TReturn>(); var addConnectionT = addEnumerableConnection.MakeGenericMethod(typeof(TSource), itemGraphType, typeof(TReturn)); addConnectionT.Invoke(this, new object?[] { graph, name, resolve, pageSize, description, arguments, includeNames }); }
FilteredConnection <TNodeType, TSourceType>(this ComplexGraphType <TSourceType> graphType) where TNodeType : GraphType { var builder = graphType.Connection <TNodeType>(); builder.FieldType.Arguments.Add( new QueryArgument(typeof(FilterGraphType <TNodeType>)) { Name = "filter", ResolvedType = new FilterGraphType <TNodeType>(graphType) } ); builder.FieldType.Arguments.Add( new QueryArgument(typeof(ListGraphType <NonNullGraphType <OrderByGraphType <TNodeType> > >)) { Name = "orderBy", ResolvedType = new ListGraphType(new NonNullGraphType(new OrderByGraphType <TNodeType>(graphType))) } ); return(builder); }