GQL dynamic query :)
This commit is contained in:
parent
ffcfc60df1
commit
edf9258a85
@ -19,6 +19,7 @@
|
|||||||
<ProjectReference Include="..\PoweredSoft.CQRS.DynamicQuery.AspNetCore\PoweredSoft.CQRS.DynamicQuery.AspNetCore.csproj" />
|
<ProjectReference Include="..\PoweredSoft.CQRS.DynamicQuery.AspNetCore\PoweredSoft.CQRS.DynamicQuery.AspNetCore.csproj" />
|
||||||
<ProjectReference Include="..\PoweredSoft.CQRS.DynamicQuery\PoweredSoft.CQRS.DynamicQuery.csproj" />
|
<ProjectReference Include="..\PoweredSoft.CQRS.DynamicQuery\PoweredSoft.CQRS.DynamicQuery.csproj" />
|
||||||
<ProjectReference Include="..\PoweredSoft.CQRS.GraphQL.FluentValidation\PoweredSoft.CQRS.GraphQL.FluentValidation.csproj" />
|
<ProjectReference Include="..\PoweredSoft.CQRS.GraphQL.FluentValidation\PoweredSoft.CQRS.GraphQL.FluentValidation.csproj" />
|
||||||
|
<ProjectReference Include="..\PoweredSoft.CQRS.GraphQL.HotChocolate.DynamicQuery\PoweredSoft.CQRS.GraphQL.HotChocolate.DynamicQuery.csproj" />
|
||||||
<ProjectReference Include="..\PoweredSoft.CQRS.GraphQL.HotChocolate\PoweredSoft.CQRS.GraphQL.HotChocolate.csproj" />
|
<ProjectReference Include="..\PoweredSoft.CQRS.GraphQL.HotChocolate\PoweredSoft.CQRS.GraphQL.HotChocolate.csproj" />
|
||||||
<ProjectReference Include="..\PoweredSoft.CQRS\PoweredSoft.CQRS.csproj" />
|
<ProjectReference Include="..\PoweredSoft.CQRS\PoweredSoft.CQRS.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
@ -4,15 +4,11 @@ using Demo.DynamicQueries;
|
|||||||
using Demo.Queries;
|
using Demo.Queries;
|
||||||
using FluentValidation;
|
using FluentValidation;
|
||||||
using FluentValidation.AspNetCore;
|
using FluentValidation.AspNetCore;
|
||||||
using HotChocolate.Types;
|
|
||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.AspNetCore.HttpsPolicy;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
using PoweredSoft.CQRS;
|
using PoweredSoft.CQRS;
|
||||||
using PoweredSoft.CQRS.Abstractions;
|
using PoweredSoft.CQRS.Abstractions;
|
||||||
using PoweredSoft.CQRS.AspNetCore.Mvc;
|
using PoweredSoft.CQRS.AspNetCore.Mvc;
|
||||||
@ -24,13 +20,11 @@ using PoweredSoft.CQRS.GraphQL.HotChocolate;
|
|||||||
using PoweredSoft.Data;
|
using PoweredSoft.Data;
|
||||||
using PoweredSoft.Data.Core;
|
using PoweredSoft.Data.Core;
|
||||||
using PoweredSoft.DynamicQuery;
|
using PoweredSoft.DynamicQuery;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using PoweredSoft.CQRS.GraphQL.HotChocolate.DynamicQuery;
|
||||||
|
|
||||||
namespace Demo
|
namespace Demo
|
||||||
{
|
{
|
||||||
public class Startup
|
public class Startup
|
||||||
{
|
{
|
||||||
public Startup(IConfiguration configuration)
|
public Startup(IConfiguration configuration)
|
||||||
@ -65,6 +59,7 @@ namespace Demo
|
|||||||
.AddGraphQLServer()
|
.AddGraphQLServer()
|
||||||
.AddQueryType(d => d.Name("Query"))
|
.AddQueryType(d => d.Name("Query"))
|
||||||
.AddPoweredSoftQueries()
|
.AddPoweredSoftQueries()
|
||||||
|
.AddPoweredSoftDynamicQueries()
|
||||||
.AddMutationType(d => d.Name("Mutation"))
|
.AddMutationType(d => d.Name("Mutation"))
|
||||||
.AddPoweredSoftMutations();
|
.AddPoweredSoftMutations();
|
||||||
|
|
||||||
@ -114,14 +109,14 @@ namespace Demo
|
|||||||
|
|
||||||
app.UseAuthorization();
|
app.UseAuthorization();
|
||||||
|
|
||||||
//app.UseSwagger();
|
app.UseSwagger();
|
||||||
|
|
||||||
// Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.),
|
// Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.),
|
||||||
// specifying the Swagger JSON endpoint.
|
// specifying the Swagger JSON endpoint.
|
||||||
//app.UseSwaggerUI(c =>
|
app.UseSwaggerUI(c =>
|
||||||
//{
|
{
|
||||||
// c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
|
c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
|
||||||
//});
|
});
|
||||||
|
|
||||||
app.UseEndpoints(endpoints =>
|
app.UseEndpoints(endpoints =>
|
||||||
{
|
{
|
||||||
|
@ -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
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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<GraphQLAdvanceQueryFilter> 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<IFilter>();
|
||||||
|
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()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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; }
|
||||||
|
}
|
||||||
|
}
|
73
PoweredSoft.CQRS.GraphQL.DynamicQuery/GraphQLDynamicQuery.cs
Normal file
73
PoweredSoft.CQRS.GraphQL.DynamicQuery/GraphQLDynamicQuery.cs
Normal file
@ -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<TSource, TDestination> : GraphQLDynamicQuery, IDynamicQuery<TSource, TDestination>
|
||||||
|
where TSource : class
|
||||||
|
where TDestination : class
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public class GraphQLDynamicQuery<TSource, TDestination, TParams> : GraphQLDynamicQuery<TSource, TDestination>,
|
||||||
|
IDynamicQuery<TSource, TDestination, TParams>
|
||||||
|
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<GraphQLSort> Sorts { get; set; }
|
||||||
|
public List<GraphQLAdvanceQueryFilter> Filters { get; set; }
|
||||||
|
public List<GraphQLAdvanceQueryGroup> Groups { get; set; }
|
||||||
|
public List<GraphQLAdvanceQueryAggregate> Aggregates { get; set; }
|
||||||
|
|
||||||
|
public List<IAggregate> GetAggregates()
|
||||||
|
{
|
||||||
|
if (Aggregates == null)
|
||||||
|
return new List<IAggregate>();
|
||||||
|
|
||||||
|
return Aggregates.Select(a => a.ToAggregate()).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<IFilter> GetFilters()
|
||||||
|
{
|
||||||
|
if (Filters == null)
|
||||||
|
return new List<IFilter>();
|
||||||
|
|
||||||
|
return Filters.Select(t => t.ToFilter()).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<IGroup> GetGroups()
|
||||||
|
{
|
||||||
|
if (Groups == null)
|
||||||
|
return new List<IGroup>();
|
||||||
|
|
||||||
|
return Groups.Select(t => t.ToGroup()).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int? GetPage() => Page;
|
||||||
|
|
||||||
|
public int? GetPageSize() => PageSize;
|
||||||
|
|
||||||
|
public List<ISort> GetSorts()
|
||||||
|
{
|
||||||
|
if (Sorts == null)
|
||||||
|
return new List<ISort>();
|
||||||
|
|
||||||
|
return Sorts.Select(t => t.ToSort()).ToList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,59 @@
|
|||||||
|
using PoweredSoft.DynamicQuery.Core;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace PoweredSoft.CQRS.GraphQL.DynamicQuery
|
||||||
|
{
|
||||||
|
public class GraphQLDynamicQueryExecutionResult<TResult> : GraphQLDynamicQueryResult<TResult>
|
||||||
|
{
|
||||||
|
public List<GraphQLDynamicQueryGroupResult<TResult>> Groups { get; set; }
|
||||||
|
public long TotalRecords { get; set; }
|
||||||
|
public long? NumberOfPages { get; set; }
|
||||||
|
|
||||||
|
public void FromResult(IQueryExecutionResult<TResult> 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<TResult> groupedResult)
|
||||||
|
Groups = groupedResult.Groups.Select(ConvertGroupResult).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual GraphQLDynamicQueryGroupResult<TResult> ConvertGroupResult(IGroupQueryResult<TResult> arg)
|
||||||
|
{
|
||||||
|
var group = new GraphQLDynamicQueryGroupResult<TResult>();
|
||||||
|
|
||||||
|
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)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace PoweredSoft.CQRS.GraphQL.DynamicQuery
|
||||||
|
{
|
||||||
|
public class GraphQLDynamicQueryGroupResult<TResult> : GraphQLDynamicQueryResult<TResult>
|
||||||
|
{
|
||||||
|
public string GroupPath { get; set; }
|
||||||
|
public GraphQLVariantResult GroupValue { get; set; }
|
||||||
|
public bool HasSubGroups => SubGroups?.Any() == true;
|
||||||
|
public List<GraphQLDynamicQueryGroupResult<TResult>> SubGroups { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace PoweredSoft.CQRS.GraphQL.DynamicQuery
|
||||||
|
{
|
||||||
|
public class GraphQLDynamicQueryResult<TResult>
|
||||||
|
{
|
||||||
|
public List<TResult> Data { get; set; }
|
||||||
|
public List<GraphQLAggregateResult> Aggregates { get; set; }
|
||||||
|
}
|
||||||
|
}
|
17
PoweredSoft.CQRS.GraphQL.DynamicQuery/GraphQLSort.cs
Normal file
17
PoweredSoft.CQRS.GraphQL.DynamicQuery/GraphQLSort.cs
Normal file
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
90
PoweredSoft.CQRS.GraphQL.DynamicQuery/GraphQLVariant.cs
Normal file
90
PoweredSoft.CQRS.GraphQL.DynamicQuery/GraphQLVariant.cs
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace PoweredSoft.CQRS.GraphQL.DynamicQuery
|
||||||
|
{
|
||||||
|
public class GraphQLVariantInput : GraphQLVariant
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netstandard2.0</TargetFramework>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||||
|
<PackageReference Include="PoweredSoft.DynamicQuery" Version="2.1.4" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\PoweredSoft.CQRS.DynamicQuery.Abstractions\PoweredSoft.CQRS.DynamicQuery.Abstractions.csproj" />
|
||||||
|
<ProjectReference Include="..\PoweredSoft.CQRS.DynamicQuery\PoweredSoft.CQRS.DynamicQuery.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
@ -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<object>("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;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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<TSource, TDestination>
|
||||||
|
where TSource : class
|
||||||
|
where TDestination : class
|
||||||
|
{
|
||||||
|
private readonly DynamicQueryHandler<TSource, TDestination> handler;
|
||||||
|
|
||||||
|
public DynamicQueryRunner(DynamicQueryHandler<TSource, TDestination> handler)
|
||||||
|
{
|
||||||
|
this.handler = handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<GraphQLDynamicQueryExecutionResult<TDestination>> RunAsync(IDynamicQuery<TSource, TDestination> query, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
var result = await handler.HandleAsync(query);
|
||||||
|
var outcome = new GraphQLDynamicQueryExecutionResult<TDestination>();
|
||||||
|
outcome.FromResult(result);
|
||||||
|
return outcome;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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<TSource, TDestination, TParams>
|
||||||
|
where TSource : class
|
||||||
|
where TDestination : class
|
||||||
|
where TParams : class
|
||||||
|
{
|
||||||
|
private readonly DynamicQueryHandler<TSource, TDestination, TParams> handler;
|
||||||
|
|
||||||
|
public DynamicQueryRunnerWithParams(DynamicQueryHandler<TSource, TDestination, TParams> handler)
|
||||||
|
{
|
||||||
|
this.handler = handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<GraphQLDynamicQueryExecutionResult<TDestination>> RunAsync(IDynamicQuery<TSource, TDestination, TParams> query, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
var result = await handler.HandleAsync(query);
|
||||||
|
var outcome = new GraphQLDynamicQueryExecutionResult<TDestination>();
|
||||||
|
outcome.FromResult(result);
|
||||||
|
return outcome;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="HotChocolate" Version="11.0.9" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\PoweredSoft.CQRS.Abstractions\PoweredSoft.CQRS.Abstractions.csproj" />
|
||||||
|
<ProjectReference Include="..\PoweredSoft.CQRS.GraphQL.DynamicQuery\PoweredSoft.CQRS.GraphQL.DynamicQuery.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
@ -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<DynamicQueryObjectType>();
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,13 +1,9 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<FrameworkReference Include="Microsoft.AspNetCore.App" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="HotChocolate" Version="11.0.9" />
|
<PackageReference Include="HotChocolate" Version="11.0.9" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
@ -31,6 +31,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PoweredSoft.CQRS.GraphQL.Ab
|
|||||||
EndProject
|
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}"
|
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
|
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
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
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}.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.ActiveCfg = Release|Any CPU
|
||||||
{BB134663-BAB0-45C4-A6E0-34F296FCA7AE}.Release|Any CPU.Build.0 = 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
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
Loading…
Reference in New Issue
Block a user