Skip to content

Commit

Permalink
Fixed static type extensions when using generics (#5690)
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelstaib committed Jan 16, 2023
1 parent a730ed5 commit 1ea8a35
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 4 deletions.
17 changes: 13 additions & 4 deletions src/HotChocolate/Core/src/Types/Types/ObjectTypeExtension.cs
Expand Up @@ -164,19 +164,28 @@ protected override ObjectTypeDefinition CreateDefinition(ITypeDiscoveryContext c
/// </summary>
internal sealed class StaticObjectTypeExtension : ObjectTypeExtension
{
private readonly Type _staticRuntimeType;
private readonly Type _staticExtType;

public StaticObjectTypeExtension(Type staticRuntimeType)
=> _staticRuntimeType = staticRuntimeType;
public StaticObjectTypeExtension(Type staticExtType)
=> _staticExtType = staticExtType;

protected override void Configure(IObjectTypeDescriptor descriptor)
{
var context = descriptor.Extend().Context;
var definition = descriptor.Extend().Definition;

// we are using the non-generic type extension class which would set nothing.
definition.Name = context.Naming.GetTypeName(_staticExtType, TypeKind.Object);
definition.Description = context.Naming.GetTypeDescription(_staticExtType, TypeKind.Object);
definition.Fields.BindingBehavior = context.Options.DefaultBindingBehavior;
definition.FieldBindingFlags = context.Options.DefaultFieldBindingFlags;
definition.FieldBindingType = _staticExtType;
definition.IsExtension = true;

// we set the static type as runtime type. Since this is not the actual runtime
// type and is replaced by the actual runtime type of the GraphQL type
// we do not run into any conflicts here.
definition.RuntimeType = _staticRuntimeType;
definition.RuntimeType = _staticExtType;

// next we set the binding flags to only infer static members.
definition.FieldBindingFlags = FieldBindingFlags.Static;
Expand Down
10 changes: 10 additions & 0 deletions src/HotChocolate/Core/src/Types/Types/ObjectTypeExtension~1.cs
Expand Up @@ -7,6 +7,16 @@

namespace HotChocolate.Types;

/// <summary>
/// <para>
/// Object type extensions are used to represent a type which has been extended
/// from some original type.
/// </para>
/// <para>
/// For example, this might be used to represent local data, or by a GraphQL service
/// which is itself an extension of another GraphQL service.
/// </para>
/// </summary>
public class ObjectTypeExtension<T> : ObjectTypeExtension
{
private Action<IObjectTypeDescriptor<T>>? _configure;
Expand Down
Expand Up @@ -728,6 +728,32 @@ public async Task Query_Extension_With_Static_Members_Execute()
SnapshotExtensions.MatchSnapshot(result);
}

[Fact]
public async Task Query_Extension_With_Static_Members_And_Generic_Schema()
{
var schema =
await new ServiceCollection()
.AddGraphQL()
.AddQueryType<FooQuery>()
.AddTypeExtension(typeof(StaticFooQueryExtensions))
.BuildSchemaAsync();

SnapshotExtensions.MatchSnapshot(schema);
}

[Fact]
public async Task Query_Extension_With_Static_Members_And_Generic()
{
var result =
await new ServiceCollection()
.AddGraphQL()
.AddQueryType<FooQuery>()
.AddTypeExtension(typeof(StaticFooQueryExtensions))
.ExecuteRequestAsync("{ hello }");

SnapshotExtensions.MatchSnapshot(result);
}

public class FooType : ObjectType<Foo>
{
protected override void Configure(IObjectTypeDescriptor<Foo> descriptor)
Expand Down Expand Up @@ -1099,4 +1125,17 @@ public static class StaticExtensions
public static string Hello()
=> "abc";
}

public class FooQuery
{
public string Abc { get; } = "def";
}

[ExtendObjectType<FooQuery>]
public static class StaticFooQueryExtensions
{
public static string Hello([Parent] FooQuery query)
=> query.Abc;
}

}
@@ -0,0 +1,5 @@
{
"data": {
"hello": "def"
}
}
@@ -0,0 +1,8 @@
schema {
query: FooQuery
}

type FooQuery {
abc: String!
hello: String!
}

0 comments on commit 1ea8a35

Please sign in to comment.