From edf9258a85ab02b8fb6170a94b3785fd7847a9d1 Mon Sep 17 00:00:00 2001 From: David Lebee Date: Thu, 4 Feb 2021 13:51:31 -0500 Subject: [PATCH] GQL dynamic query :) --- Demo/Demo.csproj | 1 + Demo/Startup.cs | 21 ++--- .../GraphQLAdvanceQueryAggregate.cs | 21 +++++ .../GraphQLAdvanceQueryFilter.cs | 49 ++++++++++ .../GraphQLAdvanceQueryGroup.cs | 21 +++++ .../GraphQLAggregateResult.cs | 11 +++ .../GraphQLDynamicQuery.cs | 73 +++++++++++++++ .../GraphQLDynamicQueryExecutionResult.cs | 59 ++++++++++++ .../GraphQLDynamicQueryGroupResult.cs | 13 +++ .../GraphQLDynamicQueryResult.cs | 10 +++ .../GraphQLSort.cs | 17 ++++ .../GraphQLVariant.cs | 90 +++++++++++++++++++ .../GraphQLVariantInput.cs | 8 ++ .../GraphQLVariantResult.cs | 60 +++++++++++++ ...weredSoft.CQRS.GraphQL.DynamicQuery.csproj | 17 ++++ .../DynamicQueryObjectType.cs | 84 +++++++++++++++++ .../DynamicQueryRunner.cs | 28 ++++++ .../DynamicQueryRunnerWithParams.cs | 29 ++++++ ...S.GraphQL.HotChocolate.DynamicQuery.csproj | 16 ++++ .../RequestExecutorBuilderExtensions.cs | 15 ++++ ...weredSoft.CQRS.GraphQL.HotChocolate.csproj | 6 +- PoweredSoft.CQRS.sln | 12 +++ 22 files changed, 643 insertions(+), 18 deletions(-) create mode 100644 PoweredSoft.CQRS.GraphQL.DynamicQuery/GraphQLAdvanceQueryAggregate.cs create mode 100644 PoweredSoft.CQRS.GraphQL.DynamicQuery/GraphQLAdvanceQueryFilter.cs create mode 100644 PoweredSoft.CQRS.GraphQL.DynamicQuery/GraphQLAdvanceQueryGroup.cs create mode 100644 PoweredSoft.CQRS.GraphQL.DynamicQuery/GraphQLAggregateResult.cs create mode 100644 PoweredSoft.CQRS.GraphQL.DynamicQuery/GraphQLDynamicQuery.cs create mode 100644 PoweredSoft.CQRS.GraphQL.DynamicQuery/GraphQLDynamicQueryExecutionResult.cs create mode 100644 PoweredSoft.CQRS.GraphQL.DynamicQuery/GraphQLDynamicQueryGroupResult.cs create mode 100644 PoweredSoft.CQRS.GraphQL.DynamicQuery/GraphQLDynamicQueryResult.cs create mode 100644 PoweredSoft.CQRS.GraphQL.DynamicQuery/GraphQLSort.cs create mode 100644 PoweredSoft.CQRS.GraphQL.DynamicQuery/GraphQLVariant.cs create mode 100644 PoweredSoft.CQRS.GraphQL.DynamicQuery/GraphQLVariantInput.cs create mode 100644 PoweredSoft.CQRS.GraphQL.DynamicQuery/GraphQLVariantResult.cs create mode 100644 PoweredSoft.CQRS.GraphQL.DynamicQuery/PoweredSoft.CQRS.GraphQL.DynamicQuery.csproj create mode 100644 PoweredSoft.CQRS.GraphQL.HotChocolate.DynamicQuery/DynamicQueryObjectType.cs create mode 100644 PoweredSoft.CQRS.GraphQL.HotChocolate.DynamicQuery/DynamicQueryRunner.cs create mode 100644 PoweredSoft.CQRS.GraphQL.HotChocolate.DynamicQuery/DynamicQueryRunnerWithParams.cs create mode 100644 PoweredSoft.CQRS.GraphQL.HotChocolate.DynamicQuery/PoweredSoft.CQRS.GraphQL.HotChocolate.DynamicQuery.csproj create mode 100644 PoweredSoft.CQRS.GraphQL.HotChocolate.DynamicQuery/RequestExecutorBuilderExtensions.cs diff --git a/Demo/Demo.csproj b/Demo/Demo.csproj index 9450b4e..dadea88 100644 --- a/Demo/Demo.csproj +++ b/Demo/Demo.csproj @@ -19,6 +19,7 @@ + diff --git a/Demo/Startup.cs b/Demo/Startup.cs index c26d25b..a7a97ff 100644 --- a/Demo/Startup.cs +++ b/Demo/Startup.cs @@ -4,15 +4,11 @@ using Demo.DynamicQueries; using Demo.Queries; using FluentValidation; using FluentValidation.AspNetCore; -using HotChocolate.Types; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.HttpsPolicy; -using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; using PoweredSoft.CQRS; using PoweredSoft.CQRS.Abstractions; using PoweredSoft.CQRS.AspNetCore.Mvc; @@ -24,13 +20,11 @@ using PoweredSoft.CQRS.GraphQL.HotChocolate; using PoweredSoft.Data; using PoweredSoft.Data.Core; using PoweredSoft.DynamicQuery; -using System; -using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; +using PoweredSoft.CQRS.GraphQL.HotChocolate.DynamicQuery; namespace Demo -{ +{ public class Startup { public Startup(IConfiguration configuration) @@ -65,6 +59,7 @@ namespace Demo .AddGraphQLServer() .AddQueryType(d => d.Name("Query")) .AddPoweredSoftQueries() + .AddPoweredSoftDynamicQueries() .AddMutationType(d => d.Name("Mutation")) .AddPoweredSoftMutations(); @@ -114,14 +109,14 @@ namespace Demo app.UseAuthorization(); - //app.UseSwagger(); + app.UseSwagger(); // Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.), // specifying the Swagger JSON endpoint. - //app.UseSwaggerUI(c => - //{ - // c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1"); - //}); + app.UseSwaggerUI(c => + { + c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1"); + }); app.UseEndpoints(endpoints => { diff --git a/PoweredSoft.CQRS.GraphQL.DynamicQuery/GraphQLAdvanceQueryAggregate.cs b/PoweredSoft.CQRS.GraphQL.DynamicQuery/GraphQLAdvanceQueryAggregate.cs new file mode 100644 index 0000000..a3d353c --- /dev/null +++ b/PoweredSoft.CQRS.GraphQL.DynamicQuery/GraphQLAdvanceQueryAggregate.cs @@ -0,0 +1,21 @@ +using PoweredSoft.DynamicQuery; +using PoweredSoft.DynamicQuery.Core; +using System; + +namespace PoweredSoft.CQRS.GraphQL +{ + public class GraphQLAdvanceQueryAggregate + { + public string Path { get; set; } + public AggregateType Type { get; set; } + + internal IAggregate ToAggregate() + { + return new Aggregate + { + Path = Path, + Type = Type + }; + } + } +} diff --git a/PoweredSoft.CQRS.GraphQL.DynamicQuery/GraphQLAdvanceQueryFilter.cs b/PoweredSoft.CQRS.GraphQL.DynamicQuery/GraphQLAdvanceQueryFilter.cs new file mode 100644 index 0000000..20464f0 --- /dev/null +++ b/PoweredSoft.CQRS.GraphQL.DynamicQuery/GraphQLAdvanceQueryFilter.cs @@ -0,0 +1,49 @@ +using PoweredSoft.DynamicQuery; +using PoweredSoft.DynamicQuery.Core; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace PoweredSoft.CQRS.GraphQL.DynamicQuery +{ + public class GraphQLAdvanceQueryFilter + { + public bool? And { get; set; } + public FilterType Type { get; set; } + public string Path { get; set; } + public GraphQLVariantInput Value { get; set; } + public bool? Not { get; set; } + + public List Filters { get; set; } + + internal IFilter ToFilter() + { + if (Type == FilterType.Composite) + { + var ret = new CompositeFilter + { + And = And, + Type = FilterType.Composite + }; + + if (Filters == null) + ret.Filters = new List(); + else + ret.Filters = Filters.Select(t => t.ToFilter()).ToList(); + + return ret; + } + else + { + return new SimpleFilter + { + And = And, + Type = Type, + Not = Not, + Path = Path, + Value = Value.GetRawObjectValue() + }; + } + } + } +} diff --git a/PoweredSoft.CQRS.GraphQL.DynamicQuery/GraphQLAdvanceQueryGroup.cs b/PoweredSoft.CQRS.GraphQL.DynamicQuery/GraphQLAdvanceQueryGroup.cs new file mode 100644 index 0000000..b0b70cd --- /dev/null +++ b/PoweredSoft.CQRS.GraphQL.DynamicQuery/GraphQLAdvanceQueryGroup.cs @@ -0,0 +1,21 @@ +using PoweredSoft.DynamicQuery; +using PoweredSoft.DynamicQuery.Core; +using System; + +namespace PoweredSoft.CQRS.GraphQL +{ + public class GraphQLAdvanceQueryGroup + { + public string Path { get; set; } + public bool? Ascending { get; set; } + + internal IGroup ToGroup() + { + return new Group + { + Path = Path, + Ascending = Ascending + }; + } + } +} diff --git a/PoweredSoft.CQRS.GraphQL.DynamicQuery/GraphQLAggregateResult.cs b/PoweredSoft.CQRS.GraphQL.DynamicQuery/GraphQLAggregateResult.cs new file mode 100644 index 0000000..7348070 --- /dev/null +++ b/PoweredSoft.CQRS.GraphQL.DynamicQuery/GraphQLAggregateResult.cs @@ -0,0 +1,11 @@ +using PoweredSoft.DynamicQuery.Core; + +namespace PoweredSoft.CQRS.GraphQL.DynamicQuery +{ + public class GraphQLAggregateResult + { + public string Path { get; set; } + public AggregateType Type { get; set; } + public GraphQLVariantResult Value { get; set; } + } +} diff --git a/PoweredSoft.CQRS.GraphQL.DynamicQuery/GraphQLDynamicQuery.cs b/PoweredSoft.CQRS.GraphQL.DynamicQuery/GraphQLDynamicQuery.cs new file mode 100644 index 0000000..f3cf550 --- /dev/null +++ b/PoweredSoft.CQRS.GraphQL.DynamicQuery/GraphQLDynamicQuery.cs @@ -0,0 +1,73 @@ +using PoweredSoft.CQRS.DynamicQuery.Abstractions; +using PoweredSoft.CQRS.GraphQL.DynamicQuery; +using PoweredSoft.DynamicQuery.Core; +using System.Collections.Generic; +using System.Linq; + +namespace PoweredSoft.CQRS.GraphQL.DynamicQuery +{ + public class GraphQLDynamicQuery : GraphQLDynamicQuery, IDynamicQuery + where TSource : class + where TDestination : class + { + + } + + public class GraphQLDynamicQuery : GraphQLDynamicQuery, + IDynamicQuery + where TSource : class + where TDestination : class + where TParams : class + { + public TParams Params { get; set; } + + public TParams GetParams() => Params; + } + + public class GraphQLDynamicQuery : IDynamicQuery + { + public int? Page { get; set; } + public int? PageSize { get; set; } + + public List Sorts { get; set; } + public List Filters { get; set; } + public List Groups { get; set; } + public List Aggregates { get; set; } + + public List GetAggregates() + { + if (Aggregates == null) + return new List(); + + return Aggregates.Select(a => a.ToAggregate()).ToList(); + } + + public List GetFilters() + { + if (Filters == null) + return new List(); + + return Filters.Select(t => t.ToFilter()).ToList(); + } + + public List GetGroups() + { + if (Groups == null) + return new List(); + + return Groups.Select(t => t.ToGroup()).ToList(); + } + + public int? GetPage() => Page; + + public int? GetPageSize() => PageSize; + + public List GetSorts() + { + if (Sorts == null) + return new List(); + + return Sorts.Select(t => t.ToSort()).ToList(); + } + } +} diff --git a/PoweredSoft.CQRS.GraphQL.DynamicQuery/GraphQLDynamicQueryExecutionResult.cs b/PoweredSoft.CQRS.GraphQL.DynamicQuery/GraphQLDynamicQueryExecutionResult.cs new file mode 100644 index 0000000..4ce2aae --- /dev/null +++ b/PoweredSoft.CQRS.GraphQL.DynamicQuery/GraphQLDynamicQueryExecutionResult.cs @@ -0,0 +1,59 @@ +using PoweredSoft.DynamicQuery.Core; +using System.Collections.Generic; +using System.Linq; + +namespace PoweredSoft.CQRS.GraphQL.DynamicQuery +{ + public class GraphQLDynamicQueryExecutionResult : GraphQLDynamicQueryResult + { + public List> Groups { get; set; } + public long TotalRecords { get; set; } + public long? NumberOfPages { get; set; } + + public void FromResult(IQueryExecutionResult queryResult) + { + TotalRecords = queryResult.TotalRecords; + NumberOfPages = queryResult.NumberOfPages; + + + if (queryResult.Aggregates != null) + Aggregates = queryResult.Aggregates.Select(ConvertAggregateResult).ToList(); + + if (queryResult.Data != null) + Data = queryResult.Data; + + if (queryResult is IQueryExecutionGroupResult groupedResult) + Groups = groupedResult.Groups.Select(ConvertGroupResult).ToList(); + } + + protected virtual GraphQLDynamicQueryGroupResult ConvertGroupResult(IGroupQueryResult arg) + { + var group = new GraphQLDynamicQueryGroupResult(); + + group.GroupPath = arg.GroupPath; + group.GroupValue = new GraphQLVariantResult(arg.GroupValue); + + if (arg.Data != null) + group.Data = arg.Data; + + if (arg.Aggregates != null) + group.Aggregates = arg.Aggregates.Select(ConvertAggregateResult).ToList(); + + if (arg.HasSubGroups) + group.SubGroups = arg.SubGroups.Select(ConvertGroupResult).ToList(); + + return group; + } + + protected virtual GraphQLAggregateResult ConvertAggregateResult(IAggregateResult arg) + { + return new GraphQLAggregateResult + { + Path = arg.Path, + Type = arg.Type, + Value = new GraphQLVariantResult(arg.Value) + }; + } + + } +} diff --git a/PoweredSoft.CQRS.GraphQL.DynamicQuery/GraphQLDynamicQueryGroupResult.cs b/PoweredSoft.CQRS.GraphQL.DynamicQuery/GraphQLDynamicQueryGroupResult.cs new file mode 100644 index 0000000..4e3b703 --- /dev/null +++ b/PoweredSoft.CQRS.GraphQL.DynamicQuery/GraphQLDynamicQueryGroupResult.cs @@ -0,0 +1,13 @@ +using System.Collections.Generic; +using System.Linq; + +namespace PoweredSoft.CQRS.GraphQL.DynamicQuery +{ + public class GraphQLDynamicQueryGroupResult : GraphQLDynamicQueryResult + { + public string GroupPath { get; set; } + public GraphQLVariantResult GroupValue { get; set; } + public bool HasSubGroups => SubGroups?.Any() == true; + public List> SubGroups { get; set; } + } +} diff --git a/PoweredSoft.CQRS.GraphQL.DynamicQuery/GraphQLDynamicQueryResult.cs b/PoweredSoft.CQRS.GraphQL.DynamicQuery/GraphQLDynamicQueryResult.cs new file mode 100644 index 0000000..fe4973b --- /dev/null +++ b/PoweredSoft.CQRS.GraphQL.DynamicQuery/GraphQLDynamicQueryResult.cs @@ -0,0 +1,10 @@ +using System.Collections.Generic; + +namespace PoweredSoft.CQRS.GraphQL.DynamicQuery +{ + public class GraphQLDynamicQueryResult + { + public List Data { get; set; } + public List Aggregates { get; set; } + } +} diff --git a/PoweredSoft.CQRS.GraphQL.DynamicQuery/GraphQLSort.cs b/PoweredSoft.CQRS.GraphQL.DynamicQuery/GraphQLSort.cs new file mode 100644 index 0000000..0e0b6c5 --- /dev/null +++ b/PoweredSoft.CQRS.GraphQL.DynamicQuery/GraphQLSort.cs @@ -0,0 +1,17 @@ +using PoweredSoft.DynamicQuery; +using PoweredSoft.DynamicQuery.Core; +using System; + +namespace PoweredSoft.CQRS.GraphQL.DynamicQuery +{ + public class GraphQLSort + { + public string Path { get; set; } + public bool? Ascending { get; set; } + + internal ISort ToSort() + { + return new Sort(Path, Ascending); + } + } +} \ No newline at end of file diff --git a/PoweredSoft.CQRS.GraphQL.DynamicQuery/GraphQLVariant.cs b/PoweredSoft.CQRS.GraphQL.DynamicQuery/GraphQLVariant.cs new file mode 100644 index 0000000..4a6401a --- /dev/null +++ b/PoweredSoft.CQRS.GraphQL.DynamicQuery/GraphQLVariant.cs @@ -0,0 +1,90 @@ +using System; + +namespace PoweredSoft.CQRS.GraphQL.DynamicQuery +{ + public abstract class GraphQLVariant + { + + protected virtual string ResolveTypeName(object value) + { + if (value != null) + { + if (value is int) + return "int"; + if (value is long) + return "long"; + if (value is string) + return "string"; + if (value is bool) + return "boolean"; + if (value is decimal) + return "decimal"; + if (value is DateTime) + return "datetime"; + } + + return null; + } + + public string GetTypeName() + { + var value = GetRawObjectValue(); + return ResolveTypeName(value); + } + + public virtual void SetVariant(object raw) + { + ClearVariant(); + if (raw != null) + { + if (raw is int rawInt) + IntValue = rawInt; + if (raw is long rawLong) + LongValue = rawLong; + if (raw is string rawStr) + StringValue = rawStr; + if (raw is bool rawBool) + BooleanValue = rawBool; + if (raw is decimal rawDec) + DecimalValue = rawDec; + if (raw is DateTime rawDt) + DateTimeValue = rawDt; + } + } + + public virtual object GetRawObjectValue() + { + if (IntValue != null && IntValue is int) + return IntValue; + if (LongValue != null && LongValue is long) + return LongValue; + if (StringValue != null && StringValue is string) + return StringValue; + if (BooleanValue != null && BooleanValue is bool) + return BooleanValue; + if (DecimalValue != null && DecimalValue is decimal) + return DecimalValue; + if (DateTimeValue != null && DateTimeValue is DateTime) + return DateTimeValue; + + return null; + } + + public int? IntValue { get; set; } + public long? LongValue { get; set; } + public string StringValue { get; set; } + public decimal? DecimalValue { get; set; } + public DateTime? DateTimeValue { get; set; } + public bool? BooleanValue { get; set; } + + public virtual void ClearVariant() + { + this.IntValue = null; + this.LongValue = null; + this.StringValue = null; + this.DecimalValue = null; + this.DateTimeValue = null; + this.BooleanValue = null; + } + } +} diff --git a/PoweredSoft.CQRS.GraphQL.DynamicQuery/GraphQLVariantInput.cs b/PoweredSoft.CQRS.GraphQL.DynamicQuery/GraphQLVariantInput.cs new file mode 100644 index 0000000..ded90f3 --- /dev/null +++ b/PoweredSoft.CQRS.GraphQL.DynamicQuery/GraphQLVariantInput.cs @@ -0,0 +1,8 @@ +using System; + +namespace PoweredSoft.CQRS.GraphQL.DynamicQuery +{ + public class GraphQLVariantInput : GraphQLVariant + { + } +} diff --git a/PoweredSoft.CQRS.GraphQL.DynamicQuery/GraphQLVariantResult.cs b/PoweredSoft.CQRS.GraphQL.DynamicQuery/GraphQLVariantResult.cs new file mode 100644 index 0000000..5ce0475 --- /dev/null +++ b/PoweredSoft.CQRS.GraphQL.DynamicQuery/GraphQLVariantResult.cs @@ -0,0 +1,60 @@ +using Newtonsoft.Json; + +namespace PoweredSoft.CQRS.GraphQL.DynamicQuery +{ + public class GraphQLVariantResult : GraphQLVariant + { + public GraphQLVariantResult() + { + + } + + public GraphQLVariantResult(object raw) + { + SetVariant(raw); + } + + protected override string ResolveTypeName(object value) + { + var valueType = base.ResolveTypeName(value); + if (value != null && valueType == null) + return "json"; + + return valueType; + } + + public override object GetRawObjectValue() + { + if (jsonValue != null) + return jsonValue; + + return base.GetRawObjectValue(); + } + + private object jsonValue = null; + + public string Json + { + get + { + if (jsonValue != null) + return JsonConvert.SerializeObject(jsonValue, new JsonSerializerSettings + { + ReferenceLoopHandling = ReferenceLoopHandling.Ignore + }); + + return null; + } + set + { + jsonValue = JsonConvert.DeserializeObject(value); + } + } + + public override void ClearVariant() + { + base.ClearVariant(); + this.jsonValue = null; + } + } +} \ No newline at end of file diff --git a/PoweredSoft.CQRS.GraphQL.DynamicQuery/PoweredSoft.CQRS.GraphQL.DynamicQuery.csproj b/PoweredSoft.CQRS.GraphQL.DynamicQuery/PoweredSoft.CQRS.GraphQL.DynamicQuery.csproj new file mode 100644 index 0000000..995173c --- /dev/null +++ b/PoweredSoft.CQRS.GraphQL.DynamicQuery/PoweredSoft.CQRS.GraphQL.DynamicQuery.csproj @@ -0,0 +1,17 @@ + + + + netstandard2.0 + + + + + + + + + + + + + diff --git a/PoweredSoft.CQRS.GraphQL.HotChocolate.DynamicQuery/DynamicQueryObjectType.cs b/PoweredSoft.CQRS.GraphQL.HotChocolate.DynamicQuery/DynamicQueryObjectType.cs new file mode 100644 index 0000000..564f955 --- /dev/null +++ b/PoweredSoft.CQRS.GraphQL.HotChocolate.DynamicQuery/DynamicQueryObjectType.cs @@ -0,0 +1,84 @@ +using HotChocolate.Types; +using PoweredSoft.CQRS.Abstractions; +using PoweredSoft.CQRS.Abstractions.Discovery; +using PoweredSoft.CQRS.DynamicQuery.Discover; +using System; + +namespace PoweredSoft.CQRS.GraphQL.HotChocolate.DynamicQuery +{ + + internal class DynamicQueryObjectType : ObjectTypeExtension + { + private readonly IQueryDiscovery queryDiscovery; + + public DynamicQueryObjectType(IQueryDiscovery queryDiscovery) : base() + { + this.queryDiscovery = queryDiscovery; + } + + protected override void Configure(IObjectTypeDescriptor descriptor) + { + base.Configure(descriptor); + descriptor.Name("Query"); + + foreach(var q in queryDiscovery.GetQueries()) + { + if (q.Category == "DynamicQuery" && q is DynamicQueryMeta dq) + { + var f = descriptor.Field(q.LowerCamelCaseName); + + // service to execute with. + var queryHandlerServiceType = typeof(IQueryHandler<,>).MakeGenericType(dq.QueryType, dq.QueryResultType); + + // destermine argument type. + Type argumentType; + Type runnerType; + if (dq.ParamsType != null) + { + argumentType = typeof(GraphQL.DynamicQuery.GraphQLDynamicQuery<,,>).MakeGenericType( + dq.SourceType, dq.DestinationType, dq.ParamsType); + + runnerType = typeof(DynamicQueryRunnerWithParams<,,>) + .MakeGenericType(dq.SourceType, dq.DestinationType, dq.ParamsType); + } + else + { + argumentType = typeof(GraphQL.DynamicQuery.GraphQLDynamicQuery<,>).MakeGenericType( + dq.SourceType, dq.DestinationType); + + runnerType = typeof(DynamicQueryRunner<,>) + .MakeGenericType(dq.SourceType, dq.DestinationType); + } + + f.Argument("params", a => a + .Type(argumentType) + .DefaultValue(Activator.CreateInstance(argumentType)) + ); + + // make generic type of outgoing type. + var resultType = typeof(GraphQL.DynamicQuery.GraphQLDynamicQueryExecutionResult<>) + .MakeGenericType(dq.DestinationType); + + f.Type(resultType); + + // resolver + f.Resolve(async r => + { + dynamic argument = r.ArgumentValue("params"); + + // handler service. + var service = r.Service(queryHandlerServiceType); + + // runner. + dynamic runner = Activator.CreateInstance(runnerType, new object[] { service }); + + // get outcome. + object outcome = await runner.RunAsync(argument, r.RequestAborted); + + return outcome; + }); + } + } + } + } +} \ No newline at end of file diff --git a/PoweredSoft.CQRS.GraphQL.HotChocolate.DynamicQuery/DynamicQueryRunner.cs b/PoweredSoft.CQRS.GraphQL.HotChocolate.DynamicQuery/DynamicQueryRunner.cs new file mode 100644 index 0000000..320012f --- /dev/null +++ b/PoweredSoft.CQRS.GraphQL.HotChocolate.DynamicQuery/DynamicQueryRunner.cs @@ -0,0 +1,28 @@ +using PoweredSoft.CQRS.DynamicQuery; +using PoweredSoft.CQRS.DynamicQuery.Abstractions; +using PoweredSoft.CQRS.GraphQL.DynamicQuery; +using System.Threading; +using System.Threading.Tasks; + +namespace PoweredSoft.CQRS.GraphQL.HotChocolate.DynamicQuery +{ + public class DynamicQueryRunner + where TSource : class + where TDestination : class + { + private readonly DynamicQueryHandler handler; + + public DynamicQueryRunner(DynamicQueryHandler handler) + { + this.handler = handler; + } + + public async Task> RunAsync(IDynamicQuery query, CancellationToken cancellationToken = default) + { + var result = await handler.HandleAsync(query); + var outcome = new GraphQLDynamicQueryExecutionResult(); + outcome.FromResult(result); + return outcome; + } + } +} \ No newline at end of file diff --git a/PoweredSoft.CQRS.GraphQL.HotChocolate.DynamicQuery/DynamicQueryRunnerWithParams.cs b/PoweredSoft.CQRS.GraphQL.HotChocolate.DynamicQuery/DynamicQueryRunnerWithParams.cs new file mode 100644 index 0000000..f40702c --- /dev/null +++ b/PoweredSoft.CQRS.GraphQL.HotChocolate.DynamicQuery/DynamicQueryRunnerWithParams.cs @@ -0,0 +1,29 @@ +using PoweredSoft.CQRS.DynamicQuery; +using PoweredSoft.CQRS.DynamicQuery.Abstractions; +using PoweredSoft.CQRS.GraphQL.DynamicQuery; +using System.Threading; +using System.Threading.Tasks; + +namespace PoweredSoft.CQRS.GraphQL.HotChocolate.DynamicQuery +{ + public class DynamicQueryRunnerWithParams + where TSource : class + where TDestination : class + where TParams : class + { + private readonly DynamicQueryHandler handler; + + public DynamicQueryRunnerWithParams(DynamicQueryHandler handler) + { + this.handler = handler; + } + + public async Task> RunAsync(IDynamicQuery query, CancellationToken cancellationToken = default) + { + var result = await handler.HandleAsync(query); + var outcome = new GraphQLDynamicQueryExecutionResult(); + outcome.FromResult(result); + return outcome; + } + } +} \ No newline at end of file diff --git a/PoweredSoft.CQRS.GraphQL.HotChocolate.DynamicQuery/PoweredSoft.CQRS.GraphQL.HotChocolate.DynamicQuery.csproj b/PoweredSoft.CQRS.GraphQL.HotChocolate.DynamicQuery/PoweredSoft.CQRS.GraphQL.HotChocolate.DynamicQuery.csproj new file mode 100644 index 0000000..c97f193 --- /dev/null +++ b/PoweredSoft.CQRS.GraphQL.HotChocolate.DynamicQuery/PoweredSoft.CQRS.GraphQL.HotChocolate.DynamicQuery.csproj @@ -0,0 +1,16 @@ + + + + netcoreapp3.1 + + + + + + + + + + + + diff --git a/PoweredSoft.CQRS.GraphQL.HotChocolate.DynamicQuery/RequestExecutorBuilderExtensions.cs b/PoweredSoft.CQRS.GraphQL.HotChocolate.DynamicQuery/RequestExecutorBuilderExtensions.cs new file mode 100644 index 0000000..6258e0b --- /dev/null +++ b/PoweredSoft.CQRS.GraphQL.HotChocolate.DynamicQuery/RequestExecutorBuilderExtensions.cs @@ -0,0 +1,15 @@ +using HotChocolate.Execution.Configuration; +using Microsoft.Extensions.DependencyInjection; +using System; + +namespace PoweredSoft.CQRS.GraphQL.HotChocolate.DynamicQuery +{ + public static class RequestExecutorBuilderExtensions + { + public static IRequestExecutorBuilder AddPoweredSoftDynamicQueries(this IRequestExecutorBuilder builder) + { + builder.AddTypeExtension(); + return builder; + } + } +} diff --git a/PoweredSoft.CQRS.GraphQL.HotChocolate/PoweredSoft.CQRS.GraphQL.HotChocolate.csproj b/PoweredSoft.CQRS.GraphQL.HotChocolate/PoweredSoft.CQRS.GraphQL.HotChocolate.csproj index 9f66a32..73245fb 100644 --- a/PoweredSoft.CQRS.GraphQL.HotChocolate/PoweredSoft.CQRS.GraphQL.HotChocolate.csproj +++ b/PoweredSoft.CQRS.GraphQL.HotChocolate/PoweredSoft.CQRS.GraphQL.HotChocolate.csproj @@ -1,13 +1,9 @@ - + netcoreapp3.1 - - - - diff --git a/PoweredSoft.CQRS.sln b/PoweredSoft.CQRS.sln index 4d09ba5..a483732 100644 --- a/PoweredSoft.CQRS.sln +++ b/PoweredSoft.CQRS.sln @@ -31,6 +31,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PoweredSoft.CQRS.GraphQL.Ab EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PoweredSoft.CQRS.GraphQL.FluentValidation", "PoweredSoft.CQRS.GraphQL.FluentValidation\PoweredSoft.CQRS.GraphQL.FluentValidation.csproj", "{BB134663-BAB0-45C4-A6E0-34F296FCA7AE}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PoweredSoft.CQRS.GraphQL.HotChocolate.DynamicQuery", "PoweredSoft.CQRS.GraphQL.HotChocolate.DynamicQuery\PoweredSoft.CQRS.GraphQL.HotChocolate.DynamicQuery.csproj", "{8921D74D-DA6E-4DAF-BE85-7BE5229FE95C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PoweredSoft.CQRS.GraphQL.DynamicQuery", "PoweredSoft.CQRS.GraphQL.DynamicQuery\PoweredSoft.CQRS.GraphQL.DynamicQuery.csproj", "{34B27880-A5D5-47EA-A5FA-86E04E0F7A21}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -81,6 +85,14 @@ Global {BB134663-BAB0-45C4-A6E0-34F296FCA7AE}.Debug|Any CPU.Build.0 = Debug|Any CPU {BB134663-BAB0-45C4-A6E0-34F296FCA7AE}.Release|Any CPU.ActiveCfg = Release|Any CPU {BB134663-BAB0-45C4-A6E0-34F296FCA7AE}.Release|Any CPU.Build.0 = Release|Any CPU + {8921D74D-DA6E-4DAF-BE85-7BE5229FE95C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8921D74D-DA6E-4DAF-BE85-7BE5229FE95C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8921D74D-DA6E-4DAF-BE85-7BE5229FE95C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8921D74D-DA6E-4DAF-BE85-7BE5229FE95C}.Release|Any CPU.Build.0 = Release|Any CPU + {34B27880-A5D5-47EA-A5FA-86E04E0F7A21}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {34B27880-A5D5-47EA-A5FA-86E04E0F7A21}.Debug|Any CPU.Build.0 = Debug|Any CPU + {34B27880-A5D5-47EA-A5FA-86E04E0F7A21}.Release|Any CPU.ActiveCfg = Release|Any CPU + {34B27880-A5D5-47EA-A5FA-86E04E0F7A21}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE