-
-
Notifications
You must be signed in to change notification settings - Fork 749
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added Parent Projection Requirements (#7431)
- Loading branch information
1 parent
90e2826
commit 8929302
Showing
30 changed files
with
865 additions
and
108 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
28 changes: 28 additions & 0 deletions
28
src/HotChocolate/Core/src/Execution/Projections/FieldRequirementsMetadata.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
#if NET6_0_OR_GREATER | ||
using System.Collections.Immutable; | ||
using HotChocolate.Types; | ||
|
||
namespace HotChocolate.Execution.Projections; | ||
|
||
internal sealed class FieldRequirementsMetadata | ||
{ | ||
private readonly Dictionary<SchemaCoordinate, ImmutableArray<PropertyNode>> _allRequirements = new(); | ||
private bool _sealed; | ||
|
||
public ImmutableArray<PropertyNode>? GetRequirements(IObjectField field) | ||
=> _allRequirements.TryGetValue(field.Coordinate, out var requirements) ? requirements : null; | ||
|
||
public void TryAddRequirements(SchemaCoordinate fieldCoordinate, ImmutableArray<PropertyNode> requirements) | ||
{ | ||
if(_sealed) | ||
{ | ||
throw new InvalidOperationException("The requirements are sealed."); | ||
} | ||
|
||
_allRequirements.TryAdd(fieldCoordinate, requirements); | ||
} | ||
|
||
public void Seal() | ||
=> _sealed = true; | ||
} | ||
#endif |
170 changes: 170 additions & 0 deletions
170
src/HotChocolate/Core/src/Execution/Projections/PropertyNode.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,170 @@ | ||
#if NET6_0_OR_GREATER | ||
using System.Reflection; | ||
|
||
namespace HotChocolate.Execution.Projections; | ||
|
||
internal sealed class PropertyNode : PropertyNodeContainer | ||
{ | ||
public PropertyNode(PropertyInfo property, List<PropertyNode>? nodes = null) | ||
: base(nodes) | ||
{ | ||
Property = property; | ||
IsArray = property.PropertyType.IsArray; | ||
|
||
if (IsArray) | ||
{ | ||
ElementType = property.PropertyType.GetElementType(); | ||
} | ||
else | ||
{ | ||
var collectionType = GetCollectionType(property.PropertyType); | ||
if (collectionType != null) | ||
{ | ||
IsCollection = true; | ||
ElementType = collectionType.GetGenericArguments()[0]; | ||
} | ||
else | ||
{ | ||
IsCollection = false; | ||
ElementType = null; | ||
} | ||
} | ||
} | ||
|
||
private PropertyNode( | ||
PropertyInfo property, | ||
List<PropertyNode>? nodes, | ||
bool isArray, | ||
bool isCollection, | ||
Type? elementType) | ||
: base(nodes) | ||
{ | ||
Property = property; | ||
IsArray = isArray; | ||
IsCollection = isCollection; | ||
ElementType = elementType; | ||
} | ||
|
||
public PropertyInfo Property { get; } | ||
|
||
public bool IsCollection { get; } | ||
|
||
public bool IsArray { get; } | ||
|
||
public bool IsArrayOrCollection => IsArray || IsCollection; | ||
|
||
public Type? ElementType { get; } | ||
|
||
public PropertyNode Clone() | ||
{ | ||
List<PropertyNode>? nodes = null; | ||
|
||
if (Nodes.Count > 0) | ||
{ | ||
nodes = new(Nodes.Count); | ||
foreach (var node in Nodes) | ||
{ | ||
nodes.Add(node.Clone()); | ||
} | ||
} | ||
|
||
return new PropertyNode(Property, nodes, IsArray, IsCollection, ElementType); | ||
} | ||
|
||
private static Type? GetCollectionType(Type type) | ||
{ | ||
if (type.IsGenericType | ||
&& type.GetGenericTypeDefinition() == typeof(ICollection<>)) | ||
{ | ||
return type; | ||
} | ||
|
||
foreach (var interfaceType in type.GetInterfaces()) | ||
{ | ||
if (interfaceType.IsGenericType | ||
&& interfaceType.GetGenericTypeDefinition() == typeof(ICollection<>)) | ||
{ | ||
return interfaceType; | ||
} | ||
} | ||
|
||
return null; | ||
} | ||
} | ||
|
||
internal class PropertyNodeContainer( | ||
List<PropertyNode>? nodes = null) | ||
: IPropertyNodeProvider | ||
{ | ||
private static readonly IReadOnlyList<PropertyNode> _emptyNodes = Array.Empty<PropertyNode>(); | ||
private List<PropertyNode>? _nodes = nodes; | ||
private bool _sealed; | ||
|
||
public IReadOnlyList<PropertyNode> Nodes | ||
=> _nodes ?? _emptyNodes; | ||
|
||
public PropertyNode AddOrGetNode(PropertyInfo property) | ||
{ | ||
if (_sealed) | ||
{ | ||
throw new InvalidOperationException("The property node container is sealed."); | ||
} | ||
|
||
_nodes ??= new(); | ||
|
||
foreach (var node in Nodes) | ||
{ | ||
if (node.Property.Name.Equals(property.Name)) | ||
{ | ||
return node; | ||
} | ||
} | ||
|
||
var newNode = new PropertyNode(property); | ||
_nodes.Add(newNode); | ||
return newNode; | ||
} | ||
|
||
public void AddNode(PropertyNode newNode) | ||
{ | ||
if (_sealed) | ||
{ | ||
throw new InvalidOperationException("The property node container is sealed."); | ||
} | ||
|
||
_nodes ??= new(); | ||
|
||
foreach (var node in Nodes) | ||
{ | ||
if (node.Property.Name.Equals(node.Property.Name)) | ||
{ | ||
throw new InvalidOperationException("Duplicate property."); | ||
} | ||
} | ||
|
||
_nodes.Add(newNode); | ||
} | ||
|
||
public void Seal() | ||
{ | ||
if (!_sealed) | ||
{ | ||
foreach (var node in Nodes) | ||
{ | ||
node.Seal(); | ||
} | ||
|
||
_sealed = true; | ||
} | ||
} | ||
} | ||
|
||
internal interface IPropertyNodeProvider | ||
{ | ||
IReadOnlyList<PropertyNode> Nodes { get; } | ||
|
||
PropertyNode AddOrGetNode(PropertyInfo property); | ||
|
||
void AddNode(PropertyNode newNode); | ||
} | ||
#endif |
Oops, something went wrong.