public GetEntityGraphQLType( IEntityDescriptor descriptor, IIndex <IEntityDescriptor, EntityGraphQLType> entityTypesByDescriptor, IIndex <IEntityDescriptor, IRepository> repositoriesByDescriptor) { Name = descriptor.Name.Camelize(); Description = $"Query a single {descriptor.Name.Humanize(LetterCasing.LowerCase)}"; ResolvedType = entityTypesByDescriptor[descriptor]; Arguments = new QueryArguments { new QueryArgument(new NonNullGraphType(new IdGraphType())) { Name = "id", Description = $"The ID of the {descriptor.Name.Humanize(LetterCasing.LowerCase)}", }, }; var repository = repositoriesByDescriptor[descriptor]; Resolver = new AsyncFieldResolver <Option <IEntity> >(async resolveContext => { // TODO: optimize var id = resolveContext.GetArgument <Guid>("id"); var entities = await repository.__UNSAFE__ListAsync(resolveContext.CancellationToken); return(entities.FirstOrNone(e => e.Id == id)); }); }
public ContentItemsFieldType(string contentItemName, ISchema schema) { Name = "ContentItems"; Type = typeof(ListGraphType <ContentItemType>); var whereInput = new ContentItemWhereInput(contentItemName); var orderByInput = new ContentItemOrderByInput(contentItemName); Arguments = new QueryArguments( new QueryArgument <ContentItemWhereInput> { Name = "where", Description = "filters the content items", ResolvedType = whereInput }, new QueryArgument <ContentItemOrderByInput> { Name = "orderBy", Description = "sort order", ResolvedType = orderByInput }, new QueryArgument <IntGraphType> { Name = "first", Description = "the first n content items", ResolvedType = new IntGraphType() }, new QueryArgument <IntGraphType> { Name = "skip", Description = "the number of content items to skip", ResolvedType = new IntGraphType() }, new QueryArgument <PublicationStatusGraphType> { Name = "status", Description = "publication status of the content item", ResolvedType = new PublicationStatusGraphType(), DefaultValue = PublicationStatusEnum.Published } ); Resolver = new AsyncFieldResolver <IEnumerable <ContentItem> >(Resolve); schema.RegisterType(whereInput); schema.RegisterType(orderByInput); schema.RegisterType <PublicationStatusGraphType>(); }
public ListEntitiesGraphQLType( IEntityDescriptor descriptor, IIndex <IEntityDescriptor, EntityGraphQLType> entityTypesByDescriptor, IIndex <IEntityDescriptor, IRepository> repositoriesByDescriptor) { Name = descriptor.Name.Pluralize().Camelize(); Description = $"Query all {descriptor.Name.Pluralize().Humanize(LetterCasing.LowerCase)}"; ResolvedType = new ListGraphType(new NonNullGraphType(entityTypesByDescriptor[descriptor])); var repository = repositoriesByDescriptor[descriptor]; Resolver = new AsyncFieldResolver <IEnumerable <IEntity> >(resolveContext => { return(repository.__UNSAFE__ListAsync(resolveContext.CancellationToken)); }); }
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); } } }
FieldType BuildSingleField <TSource, TReturn>( string name, Func <ResolveEfFieldContext <TDbContext, TSource>, IQueryable <TReturn> > resolve, Func <ResolveEfFieldContext <TDbContext, TSource>, TReturn, Task>?mutate, IEnumerable <QueryArgument>?arguments, Type?graphType, bool nullable, string?description) where TReturn : class { Guard.AgainstWhiteSpace(nameof(name), name); graphType ??= GraphTypeFinder.FindGraphType <TReturn>(nullable); var hasId = keyNames.ContainsKey(typeof(TReturn)); return(new() { Name = name, Type = graphType, Description = description, Arguments = ArgumentAppender.GetQueryArguments(arguments, hasId, false), Resolver = new AsyncFieldResolver <TSource, TReturn?>( async context => { var efFieldContext = BuildContext(context); var names = GetKeyNames <TReturn>(); var query = resolve(efFieldContext); if (disableTracking) { query = query.AsNoTracking(); } query = includeAppender.AddIncludes(query, context); query = query.ApplyGraphQlArguments(context, names, false); var single = await query.SingleOrDefaultAsync(context.CancellationToken); if (single != null) { if (await efFieldContext.Filters.ShouldInclude(context.UserContext, single)) { if (mutate != null) { await mutate.Invoke(efFieldContext, single); } return single; } } if (nullable) { return null; } throw new ExecutionError("Not found"); }) }); }
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 }; } }
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); } }