Skip to content

Commit

Permalink
Allow static node resolver to be defined in base classes (#5002)
Browse files Browse the repository at this point in the history
  • Loading branch information
Suzii authored and michaelstaib committed May 4, 2022
1 parent 4bed0c0 commit a4b0c8d
Show file tree
Hide file tree
Showing 8 changed files with 242 additions and 43 deletions.
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#nullable enable

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
Expand All @@ -10,18 +12,15 @@
using HotChocolate.Utilities;
using CompDefaultValueAttribute = System.ComponentModel.DefaultValueAttribute;
using TypeInfo = HotChocolate.Internal.TypeInfo;

#nullable enable
using static System.Reflection.BindingFlags;

namespace HotChocolate.Types.Descriptors;

/// <summary>
/// The default type inspector implementation that provides helpers to inspect .NET types and
/// infer GraphQL type structures.
/// </summary>
public class DefaultTypeInspector
: Convention
, ITypeInspector
public class DefaultTypeInspector : Convention, ITypeInspector
{
private const string _toString = "ToString";
private const string _getHashCode = "GetHashCode";
Expand Down Expand Up @@ -67,7 +66,7 @@ public virtual bool IsMemberIgnored(MemberInfo member)
}

private IEnumerable<MemberInfo> GetMembersInternal(Type type, bool includeIgnored) =>
type.GetMembers(BindingFlags.Instance | BindingFlags.Public)
type.GetMembers(Instance | Public)
.Where(m => CanBeHandled(m, includeIgnored));

/// <inheritdoc />
Expand Down Expand Up @@ -106,7 +105,9 @@ public virtual IExtendedType GetReturnType(

IExtendedType returnType = ExtendedType.FromMember(member, _typeCache);

return ignoreAttributes ? returnType : ApplyTypeAttributes(returnType, member);
return ignoreAttributes
? returnType
: ApplyTypeAttributes(returnType, member);
}

/// <inheritdoc />
Expand Down Expand Up @@ -148,12 +149,14 @@ public IExtendedType GetArgumentType(
}

IExtendedType argumentType = GetArgumentTypeInternal(parameter);
return ignoreAttributes ? argumentType : ApplyTypeAttributes(argumentType, parameter);
return ignoreAttributes
? argumentType
: ApplyTypeAttributes(argumentType, parameter);
}

private IExtendedType GetArgumentTypeInternal(ParameterInfo parameter)
{
MethodInfo method = (MethodInfo)parameter.Member;
var method = (MethodInfo)parameter.Member;

if (!_methods.TryGetValue(method, out ExtendedMethodInfo? info))
{
Expand Down Expand Up @@ -192,10 +195,10 @@ public IExtendedType GetType(Type type, params bool?[] nullable)

if (nullable is null)
{
throw new ArgumentNullException(nameof(type));
throw new ArgumentNullException(nameof(nullable));
}

ExtendedType extendedType = ExtendedType.FromType(type, _typeCache);
var extendedType = ExtendedType.FromType(type, _typeCache);

return nullable is { Length: > 0 }
? ExtendedType.Tools.ChangeNullability(extendedType, nullable, _typeCache)
Expand All @@ -210,7 +213,7 @@ public IExtendedType GetType(Type type, ReadOnlySpan<bool?> nullable)
throw new ArgumentNullException(nameof(type));
}

ExtendedType extendedType = ExtendedType.FromType(type, _typeCache);
var extendedType = ExtendedType.FromType(type, _typeCache);

return nullable is { Length: > 0 }
? ExtendedType.Tools.ChangeNullability(extendedType, nullable, _typeCache)
Expand All @@ -227,7 +230,7 @@ public virtual IEnumerable<object> GetEnumValues(Type enumType)

if (enumType != typeof(object) && enumType.IsEnum)
{
return Enum.GetValues(enumType).Cast<object>()!;
return Enum.GetValues(enumType).Cast<object>();
}

return Enumerable.Empty<object>();
Expand Down Expand Up @@ -278,7 +281,7 @@ public virtual IEnumerable<object> GetEnumValues(Type enumType)
if (resolverType is null)
{
return nodeType
.GetMembers(BindingFlags.Static | BindingFlags.Public)
.GetMembers(Static | Public | FlattenHierarchy)
.OfType<MethodInfo>()
.FirstOrDefault(m => IsPossibleNodeResolver(m, nodeType));
}
Expand All @@ -287,7 +290,7 @@ public virtual IEnumerable<object> GetEnumValues(Type enumType)
// include the type name and can be an instance method.
// first we will check for static load methods.
MethodInfo? method = resolverType
.GetMembers(BindingFlags.Static | BindingFlags.Public)
.GetMembers(Static | Public | FlattenHierarchy)
.OfType<MethodInfo>()
.FirstOrDefault(m => IsPossibleExternalNodeResolver(m, nodeType));

Expand Down Expand Up @@ -547,7 +550,7 @@ private IExtendedType ApplyTypeAttributes(
{
IExtendedType resultType = type;

bool hasGraphQLTypeAttribute = false;
var hasGraphQLTypeAttribute = false;

if (TryGetAttribute(attributeProvider, out GraphQLTypeAttribute? typeAttribute) &&
typeAttribute.Type is { } attributeType)
Expand Down Expand Up @@ -616,7 +619,7 @@ private bool CanBeHandled(MemberInfo member, bool includeIgnored)
if (member is PropertyInfo property)
{
return CanHandleReturnType(member, property.PropertyType) &&
property.GetIndexParameters().Length == 0;
property.GetIndexParameters().Length == 0;
}

if (member is MethodInfo method &&
Expand Down Expand Up @@ -674,8 +677,7 @@ private static bool CanHandleReturnType(MemberInfo member, Type returnType)
}

#if NETSTANDARD2_0
if (returnType.IsByRef)

if (returnType.IsByRef)
#else
if (returnType.IsByRefLike ||
returnType.IsByRef)
Expand Down Expand Up @@ -738,9 +740,9 @@ private static bool CanHandleParameter(ParameterInfo parameter)
// by ref and out will never be allowed
if (parameter.ParameterType.IsByRef ||
#if !NETSTANDARD2_0
parameter.ParameterType.IsByRefLike ||
parameter.ParameterType.IsByRefLike ||
#endif
parameter.IsOut)
parameter.IsOut)
{
return false;
}
Expand All @@ -755,34 +757,32 @@ private static bool CanHandleParameter(ParameterInfo parameter)

private static bool HasConfiguration(ICustomAttributeProvider element)
=> element.IsDefined(typeof(GraphQLTypeAttribute), true) ||
element.IsDefined(typeof(ParentAttribute), true) ||
element.IsDefined(typeof(ServiceAttribute), true) ||
element.IsDefined(typeof(GlobalStateAttribute), true) ||
element.IsDefined(typeof(ScopedServiceAttribute), true) ||
element.IsDefined(typeof(ScopedStateAttribute), true) ||
element.IsDefined(typeof(LocalStateAttribute), true) ||
element.IsDefined(typeof(DescriptorAttribute), true);
element.IsDefined(typeof(ParentAttribute), true) ||
element.IsDefined(typeof(ServiceAttribute), true) ||
element.IsDefined(typeof(GlobalStateAttribute), true) ||
element.IsDefined(typeof(ScopedServiceAttribute), true) ||
element.IsDefined(typeof(ScopedStateAttribute), true) ||
element.IsDefined(typeof(LocalStateAttribute), true) ||
element.IsDefined(typeof(DescriptorAttribute), true);

private static bool IsSystemMember(MemberInfo member)
{
return IsCloneMember(member) ||
IsToString(member) ||
IsGetHashCode(member) ||
IsEquals(member);
}
=> IsCloneMember(member) ||
IsToString(member) ||
IsGetHashCode(member) ||
IsEquals(member);

private static bool IsToString(MemberInfo member)
=> member is MethodInfo { Name: _toString };

private static bool IsGetHashCode(MemberInfo member)
=> member is MethodInfo { Name: _getHashCode } m &&
m.GetParameters().Length == 0;
m.GetParameters().Length == 0;

private static bool IsEquals(MemberInfo member)
=> member is MethodInfo { Name: _equals };

private static bool IsCloneMember(MemberInfo member) =>
member.Name.EqualsOrdinal(_clone);
private static bool IsCloneMember(MemberInfo member)
=> member.Name.EqualsOrdinal(_clone);

private IEnumerable<T> GetCustomAttributes<T>(
ICustomAttributeProvider attributeProvider,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
#nullable enable

using System;
using System.Linq;
using System.Reflection;
using HotChocolate.Types.Descriptors;
using HotChocolate.Types.Descriptors.Definitions;
using HotChocolate.Types.Relay.Descriptors;
using static System.Reflection.BindingFlags;
using static HotChocolate.Utilities.ThrowHelper;

#nullable enable

namespace HotChocolate.Types.Relay;

/// <summary>
Expand Down Expand Up @@ -74,7 +75,9 @@ public override void OnConfigure(
{
if (NodeResolver is not null)
{
MethodInfo? method = NodeResolverType.GetMethod(NodeResolver);
MethodInfo? method = NodeResolverType.GetMethod(
NodeResolver,
Instance | Static | Public | FlattenHierarchy);

if (method is null)
{
Expand All @@ -92,7 +95,9 @@ public override void OnConfigure(
}
else if (NodeResolver is not null)
{
MethodInfo? method = type.GetMethod(NodeResolver);
MethodInfo? method = type.GetMethod(
NodeResolver,
Instance | Static | Public | FlattenHierarchy);

if (method is null)
{
Expand Down Expand Up @@ -132,8 +137,8 @@ public override void OnConfigure(

// we trigger a late id field configuration
var descriptor = ObjectTypeDescriptor.From(
descriptorContext.DescriptorContext,
definition);
descriptorContext.DescriptorContext,
definition);
nodeDescriptor.ConfigureNodeField(descriptor);
descriptor.CreateDefinition();

Expand Down
Loading

0 comments on commit a4b0c8d

Please sign in to comment.