Skip to content

Commit

Permalink
Added attributes for filtering and sorting (#2453)
Browse files Browse the repository at this point in the history
Co-authored-by: Michael Staib <michael@chillicream.com>
  • Loading branch information
PascalSenn and michaelstaib committed Oct 18, 2020
1 parent b8b4b0b commit 00b1234
Show file tree
Hide file tree
Showing 12 changed files with 382 additions and 3 deletions.
Expand Up @@ -71,12 +71,13 @@ public static class FieldDescriptorUtilities

foreach (TMember member in members)
{
if (include?.Invoke(members, member) ?? true)
if (include?.Invoke(members, member) ?? true)
{
TField fieldDefinition = createdFieldDefinition(member);

if (!handledMembers.Contains(member)
&& !fields.ContainsKey(fieldDefinition.Name))
if (!handledMembers.Contains(member) &&
!fields.ContainsKey(fieldDefinition.Name) &&
!fieldDefinition.Ignore)
{
handledMembers.Add(member);
fields[fieldDefinition.Name] = fieldDefinition;
Expand Down
@@ -0,0 +1,32 @@
using System;
using System.Reflection;
using HotChocolate.Types;
using HotChocolate.Types.Descriptors;

namespace HotChocolate.Data.Filters
{
[AttributeUsage(
AttributeTargets.Property | AttributeTargets.Method,
Inherited = true,
AllowMultiple = true)]
public abstract class FilterFieldDescriptorAttribute
: DescriptorAttribute
{
protected sealed override void TryConfigure(
IDescriptorContext context,
IDescriptor descriptor,
ICustomAttributeProvider element)
{
if (descriptor is IFilterFieldDescriptor d &&
element is MemberInfo m)
{
OnConfigure(context, d, m);
}
}

public abstract void OnConfigure(
IDescriptorContext context,
IFilterFieldDescriptor descriptor,
MemberInfo member);
}
}
@@ -0,0 +1,32 @@
using System;
using System.Reflection;
using HotChocolate.Types;
using HotChocolate.Types.Descriptors;

namespace HotChocolate.Data.Filters
{
[AttributeUsage(
AttributeTargets.Class | AttributeTargets.Struct,
Inherited = true,
AllowMultiple = true)]
public abstract class FilterInputTypeDescriptorAttribute
: DescriptorAttribute
{
protected sealed override void TryConfigure(
IDescriptorContext context,
IDescriptor descriptor,
ICustomAttributeProvider element)
{
if (descriptor is IFilterInputTypeDescriptor d &&
element is Type t)
{
OnConfigure(context, d, t);
}
}

public abstract void OnConfigure(
IDescriptorContext context,
IFilterInputTypeDescriptor descriptor,
Type type);
}
}
@@ -0,0 +1,32 @@
using System;
using System.Reflection;
using HotChocolate.Types;
using HotChocolate.Types.Descriptors;

namespace HotChocolate.Data.Sorting
{
[AttributeUsage(
AttributeTargets.Property | AttributeTargets.Method,
Inherited = true,
AllowMultiple = true)]
public abstract class SortFieldDescriptorAttribute
: DescriptorAttribute
{
protected sealed override void TryConfigure(
IDescriptorContext context,
IDescriptor descriptor,
ICustomAttributeProvider element)
{
if (descriptor is ISortFieldDescriptor d &&
element is MemberInfo m)
{
OnConfigure(context, d, m);
}
}

public abstract void OnConfigure(
IDescriptorContext context,
ISortFieldDescriptor descriptor,
MemberInfo member);
}
}
@@ -0,0 +1,32 @@
using System;
using System.Reflection;
using HotChocolate.Types;
using HotChocolate.Types.Descriptors;

namespace HotChocolate.Data.Sorting
{
[AttributeUsage(
AttributeTargets.Class | AttributeTargets.Struct,
Inherited = true,
AllowMultiple = true)]
public abstract class SortInputTypeDescriptorAttribute
: DescriptorAttribute
{
protected sealed override void TryConfigure(
IDescriptorContext context,
IDescriptor descriptor,
ICustomAttributeProvider element)
{
if (descriptor is ISortInputTypeDescriptor d &&
element is Type t)
{
OnConfigure(context, d, t);
}
}

public abstract void OnConfigure(
IDescriptorContext context,
ISortInputTypeDescriptor descriptor,
Type type);
}
}
Expand Up @@ -17,6 +17,11 @@ public sealed class UseSortingAttribute : ObjectFieldDescriptorAttribute
&& m.GetParameters().Length == 2
&& m.GetParameters()[0].ParameterType == typeof(IObjectFieldDescriptor));

public UseSortingAttribute(Type? sortingType = null)
{
Type = sortingType;
}

/// <summary>
/// Gets or sets the sort type which specifies the sort object structure.
/// </summary>
Expand Down
@@ -1,5 +1,8 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using HotChocolate.Types;
using HotChocolate.Types.Descriptors;
using Snapshooter.Xunit;
using Xunit;

Expand Down Expand Up @@ -49,6 +52,20 @@ public void Create_Schema_With_FilterType_With_Fluent_API()
schema.ToString().MatchSnapshot();
}

[Fact]
public void Create_Schema_With_FilterAttributes()
{
// arrange
// act
ISchema schema = SchemaBuilder.New()
.AddQueryType<Query4>()
.AddFiltering()
.Create();

// assert
schema.ToString().MatchSnapshot();
}

public class Query1
{
[UseFiltering]
Expand Down Expand Up @@ -94,6 +111,19 @@ public class Query3
};
}

public class Query4
{
[UseFiltering]
public IEnumerable<Bar> Bars { get; } = new[]
{
new Bar { Baz = 1 },
new Bar { Baz = 2 },
new Bar { Baz = 2 },
new Bar { Baz = 2 },
new Bar { Baz = 2 },
};
}

public class FooFilterType : FilterInputType<Foo>
{
protected override void Configure(IFilterInputTypeDescriptor<Foo> descriptor)
Expand All @@ -112,5 +142,36 @@ public class Foo
[GraphQLType(typeof(IntType))]
public int? Qux { get; set; }
}

[FilterTest]
public class Bar
{
public long Baz { get; set; }

[IgnoreFilterField]
public int? ShouldNotBeVisible { get; set; }
}

public class FilterTestAttribute : FilterInputTypeDescriptorAttribute
{
public override void OnConfigure(
IDescriptorContext context,
IFilterInputTypeDescriptor descriptor,
Type type)
{
descriptor.Name("ItWorks");
}
}

public class IgnoreFilterFieldAttribute : FilterFieldDescriptorAttribute
{
public override void OnConfigure(
IDescriptorContext context,
IFilterFieldDescriptor descriptor,
MemberInfo member)
{
descriptor.Ignore();
}
}
}
}
@@ -0,0 +1,39 @@
schema {
query: Query4
}

type Bar {
baz: Long!
shouldNotBeVisible: Int
}

type Query4 {
bars(where: ItWorks): [Bar!]!
}

input ComparableOperationFilterInputOfInt64FilterInput {
eq: Long
neq: Long
in: [Long!]
nin: [Long!]
gt: Long
ngt: Long
gte: Long
ngte: Long
lt: Long
nlt: Long
lte: Long
nlte: Long
}

input ItWorks {
and: [ItWorks!]
or: [ItWorks!]
baz: ComparableOperationFilterInputOfInt64FilterInput
}

"The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1."
scalar Int

"The `Long` scalar type represents non-fractional signed whole 64-bit numeric values. Long can represent values between -(2^63) and 2^63 - 1."
scalar Long

0 comments on commit 00b1234

Please sign in to comment.