Skip to content

Commit b863a40

Browse files
committed
Reworked type extension registration.
1 parent 213b429 commit b863a40

File tree

11 files changed

+131
-192
lines changed

11 files changed

+131
-192
lines changed

src/HotChocolate/Core/src/Types.Analyzers/FileBuilders/ModuleFileBuilder.cs

Lines changed: 12 additions & 170 deletions
Original file line numberDiff line numberDiff line change
@@ -79,188 +79,30 @@ public void WriteRegisterTypeExtension(string typeName, bool staticType)
7979
: "builder.AddTypeExtension<global::{0}>();",
8080
typeName);
8181

82-
public void WriteRegisterObjectTypeExtension(string runtimeTypeName, string extensionType)
83-
{
84-
_writer.WriteIndentedLine(
85-
"AddObjectTypeExtension_8734371<{0}>(builder, {1}.Initialize);",
86-
runtimeTypeName,
87-
extensionType);
88-
}
82+
public void WriteEnsureObjectTypeExtensionIsRegistered(string runtimeTypeName)
83+
=> _writer.WriteIndentedLine("builder.AddType<ObjectType<{0}>>();", runtimeTypeName);
8984

90-
public void WriteRegisterInterfaceTypeExtension(string runtimeTypeName, string extensionType)
91-
{
92-
_writer.WriteIndentedLine(
93-
"AddInterfaceTypeExtension_8734371<{0}>(builder, {1}.Initialize);",
94-
runtimeTypeName,
95-
extensionType);
96-
}
85+
public void WriteEnsureInterfaceTypeExtensionIsRegistered(string runtimeTypeName)
86+
=> _writer.WriteIndentedLine("builder.AddType<InterfaceType<{0}>>();", runtimeTypeName);
9787

98-
public void WriteRegisterObjectTypeExtensionHelpers()
88+
public void WriteRegisterObjectTypeExtension(string runtimeTypeName, string extensionType)
9989
{
100-
_writer.WriteLine();
101-
_writer.WriteIndentedLine("private static void AddObjectTypeExtension_8734371<T>(");
102-
90+
_writer.WriteIndentedLine("global::{0}.TryAdd<{1}>(", WellKnownTypes.TypeConfiguration, runtimeTypeName);
10391
using (_writer.IncreaseIndent())
10492
{
105-
_writer.WriteIndentedLine("global::HotChocolate.Execution.Configuration.IRequestExecutorBuilder builder,");
106-
_writer.WriteIndentedLine("Action<IObjectTypeDescriptor<T>> initialize)");
107-
}
108-
109-
_writer.WriteIndentedLine("{");
110-
111-
using (_writer.IncreaseIndent())
112-
{
113-
_writer.WriteIndentedLine("builder.ConfigureSchema(sb =>");
114-
_writer.WriteIndentedLine("{");
115-
116-
using (_writer.IncreaseIndent())
117-
{
118-
_writer.WriteIndentedLine("string typeName = typeof(T).FullName!;");
119-
_writer.WriteIndentedLine("string typeKey = $\"8734371_Type_ObjectType<{typeName}>\";");
120-
_writer.WriteIndentedLine("string hooksKey = $\"8734371_Hooks_ObjectType<{typeName}>\";");
121-
_writer.WriteLine();
122-
_writer.WriteIndentedLine("if (!sb.ContextData.ContainsKey(typeKey))");
123-
_writer.WriteIndentedLine("{");
124-
125-
using (_writer.IncreaseIndent())
126-
{
127-
_writer.WriteIndentedLine("sb.AddObjectType<T>(");
128-
using (_writer.IncreaseIndent())
129-
{
130-
_writer.WriteIndentedLine("descriptor =>");
131-
_writer.WriteIndentedLine("{");
132-
133-
using (_writer.IncreaseIndent())
134-
{
135-
_writer.WriteIndentedLine(
136-
"var hooks = (global::System.Collections.Generic.List<"
137-
+ "Action<IObjectTypeDescriptor<T>>>)"
138-
+ "descriptor.Extend().Context.ContextData[hooksKey]!;");
139-
_writer.WriteIndentedLine("foreach (var configure in hooks)");
140-
_writer.WriteIndentedLine("{");
141-
142-
using (_writer.IncreaseIndent())
143-
{
144-
_writer.WriteIndentedLine("configure(descriptor);");
145-
}
146-
147-
_writer.WriteIndentedLine("};");
148-
}
149-
150-
_writer.WriteIndentedLine("});");
151-
}
152-
153-
_writer.WriteIndentedLine("sb.ContextData.Add(typeKey, null);");
154-
}
155-
156-
_writer.WriteIndentedLine("}");
157-
_writer.WriteLine();
158-
159-
_writer.WriteIndentedLine("if (!sb.ContextData.TryGetValue(hooksKey, out var value))");
160-
_writer.WriteIndentedLine("{");
161-
162-
using (_writer.IncreaseIndent())
163-
{
164-
_writer.WriteIndentedLine(
165-
"value = new System.Collections.Generic.List<Action<IObjectTypeDescriptor<T>>>();");
166-
_writer.WriteIndentedLine("sb.ContextData.Add(hooksKey, value);");
167-
}
168-
169-
_writer.WriteIndentedLine("}");
170-
_writer.WriteLine();
171-
_writer.WriteIndentedLine(
172-
"((System.Collections.Generic.List<Action<IObjectTypeDescriptor<T>>>)value!)"
173-
+ ".Add(initialize);");
174-
}
175-
176-
_writer.WriteIndentedLine("});");
93+
_writer.WriteIndentedLine("\"{0}\",", extensionType);
94+
_writer.WriteIndentedLine("() => {0}.Initialize);", extensionType);
17795
}
178-
179-
_writer.WriteIndentedLine("}");
18096
}
18197

182-
public void WriteRegisterInterfaceTypeExtensionHelpers()
98+
public void WriteRegisterInterfaceTypeExtension(string runtimeTypeName, string extensionType)
18399
{
184-
_writer.WriteLine();
185-
_writer.WriteIndentedLine("private static void AddInterfaceTypeExtension_8734371<T>(");
186-
187-
using (_writer.IncreaseIndent())
188-
{
189-
_writer.WriteIndentedLine("global::HotChocolate.Execution.Configuration.IRequestExecutorBuilder builder,");
190-
_writer.WriteIndentedLine("Action<IInterfaceTypeDescriptor<T>> initialize)");
191-
}
192-
193-
_writer.WriteIndentedLine("{");
194-
100+
_writer.WriteIndentedLine("global::{0}.TryAdd<{1}>(", WellKnownTypes.TypeConfiguration, runtimeTypeName);
195101
using (_writer.IncreaseIndent())
196102
{
197-
_writer.WriteIndentedLine("builder.ConfigureSchema(sb =>");
198-
_writer.WriteIndentedLine("{");
199-
200-
using (_writer.IncreaseIndent())
201-
{
202-
_writer.WriteIndentedLine("string typeName = typeof(T).FullName!;");
203-
_writer.WriteIndentedLine("string typeKey = $\"8734371_Type_InterfaceType<{typeName}>\";");
204-
_writer.WriteIndentedLine("string hooksKey = $\"8734371_Hooks_InterfaceType<{typeName}>\";");
205-
_writer.WriteLine();
206-
_writer.WriteIndentedLine("if (!sb.ContextData.ContainsKey(typeKey))");
207-
_writer.WriteIndentedLine("{");
208-
209-
using (_writer.IncreaseIndent())
210-
{
211-
_writer.WriteIndentedLine("sb.AddInterfaceType<T>(");
212-
using (_writer.IncreaseIndent())
213-
{
214-
_writer.WriteIndentedLine("descriptor =>");
215-
_writer.WriteIndentedLine("{");
216-
217-
using (_writer.IncreaseIndent())
218-
{
219-
_writer.WriteIndentedLine(
220-
"var hooks = (global::System.Collections.Generic.List<"
221-
+ "Action<IInterfaceTypeDescriptor<T>>>)"
222-
+ "descriptor.Extend().Context.ContextData[hooksKey]!;");
223-
_writer.WriteIndentedLine("foreach (var configure in hooks)");
224-
_writer.WriteIndentedLine("{");
225-
226-
using (_writer.IncreaseIndent())
227-
{
228-
_writer.WriteIndentedLine("configure(descriptor);");
229-
}
230-
231-
_writer.WriteIndentedLine("};");
232-
}
233-
234-
_writer.WriteIndentedLine("});");
235-
}
236-
237-
_writer.WriteIndentedLine("sb.ContextData.Add(typeKey, null);");
238-
}
239-
240-
_writer.WriteIndentedLine("}");
241-
_writer.WriteLine();
242-
243-
_writer.WriteIndentedLine("if (!sb.ContextData.TryGetValue(hooksKey, out var value))");
244-
_writer.WriteIndentedLine("{");
245-
246-
using (_writer.IncreaseIndent())
247-
{
248-
_writer.WriteIndentedLine(
249-
"value = new System.Collections.Generic.List<Action<IInterfaceTypeDescriptor<T>>>();");
250-
_writer.WriteIndentedLine("sb.ContextData.Add(hooksKey, value);");
251-
}
252-
253-
_writer.WriteIndentedLine("}");
254-
_writer.WriteLine();
255-
_writer.WriteIndentedLine(
256-
"((System.Collections.Generic.List<Action<IInterfaceTypeDescriptor<T>>>)value!)"
257-
+ ".Add(initialize);");
258-
}
259-
260-
_writer.WriteIndentedLine("});");
103+
_writer.WriteIndentedLine("\"{0}\",", extensionType);
104+
_writer.WriteIndentedLine("() => {0}.Initialize);", extensionType);
261105
}
262-
263-
_writer.WriteIndentedLine("}");
264106
}
265107

266108
public void WriteRegisterDataLoader(string typeName)

src/HotChocolate/Core/src/Types.Analyzers/Generators/TypeModuleSyntaxGenerator.cs

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,9 @@ private static void WriteConfiguration(
5959
generator.WriteBeginRegistrationMethod();
6060

6161
var operations = OperationType.No;
62-
var hasObjectTypeExtensions = false;
63-
var hasInterfaceTypes = false;
6462
var hasConfigurations = false;
63+
List<string>? _objectTypeExtensions = null;
64+
List<string>? _interfaceTypeExtensions = null;
6565

6666
foreach (var syntaxInfo in syntaxInfos.OrderBy(s => s.OrderByKey))
6767
{
@@ -148,11 +148,12 @@ private static void WriteConfiguration(
148148
if ((module.Options & ModuleOptions.RegisterTypes) == ModuleOptions.RegisterTypes
149149
&& objectTypeExtension.Diagnostics.Length == 0)
150150
{
151-
hasObjectTypeExtensions = true;
152151
generator.WriteRegisterObjectTypeExtension(
153152
objectTypeExtension.RuntimeType.ToFullyQualified(),
154153
objectTypeExtension.Type.ToFullyQualified());
155154
hasConfigurations = true;
155+
_objectTypeExtensions ??= [];
156+
_objectTypeExtensions.Add(objectTypeExtension.RuntimeType.ToFullyQualified());
156157
}
157158

158159
break;
@@ -161,11 +162,12 @@ private static void WriteConfiguration(
161162
if ((module.Options & ModuleOptions.RegisterTypes) == ModuleOptions.RegisterTypes
162163
&& interfaceType.Diagnostics.Length == 0)
163164
{
164-
hasInterfaceTypes = true;
165165
generator.WriteRegisterInterfaceTypeExtension(
166166
interfaceType.RuntimeType.ToFullyQualified(),
167167
interfaceType.Type.ToFullyQualified());
168168
hasConfigurations = true;
169+
_interfaceTypeExtensions ??= [];
170+
_interfaceTypeExtensions.Add(interfaceType.RuntimeType.ToFullyQualified());
169171
}
170172

171173
break;
@@ -198,20 +200,23 @@ private static void WriteConfiguration(
198200
}
199201
}
200202

201-
generator.WriteEndRegistrationMethod();
202-
203-
if (hasObjectTypeExtensions)
203+
if (_objectTypeExtensions is not null)
204204
{
205-
generator.WriteRegisterObjectTypeExtensionHelpers();
206-
hasConfigurations = true;
205+
foreach (var type in _objectTypeExtensions)
206+
{
207+
generator.WriteEnsureObjectTypeExtensionIsRegistered(type);
208+
}
207209
}
208210

209-
if (hasInterfaceTypes)
211+
if (_interfaceTypeExtensions is not null)
210212
{
211-
generator.WriteRegisterInterfaceTypeExtensionHelpers();
212-
hasConfigurations = true;
213+
foreach (var type in _interfaceTypeExtensions)
214+
{
215+
generator.WriteEnsureInterfaceTypeExtensionIsRegistered(type);
216+
}
213217
}
214218

219+
generator.WriteEndRegistrationMethod();
215220
generator.WriteEndClass();
216221
generator.WriteEndNamespace();
217222

src/HotChocolate/Core/src/Types.Analyzers/WellKnownTypes.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ public static class WellKnownTypes
7171
public const string PagingArguments = "HotChocolate.Pagination.PagingArguments";
7272
public const string DataContext = "HotChocolate.Data.DataContext";
7373
public const string DataContextGeneric = DataContext + "<";
74-
74+
public const string TypeConfiguration = "HotChocolate.Configuration.TypeConfiguration";
7575

7676
public static HashSet<string> TypeClass { get; } =
7777
[
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
using System.Collections.Concurrent;
2+
using System.ComponentModel;
3+
using HotChocolate.Types;
4+
5+
namespace HotChocolate.Configuration;
6+
7+
public static class TypeConfiguration
8+
{
9+
private static readonly object _sync = new();
10+
private static readonly HashSet<string> _created = [];
11+
private static readonly Dictionary<Type, List<object>> _configurations = [];
12+
13+
public static void TryAdd<TRuntimeType>(
14+
string key,
15+
Func<Action<IObjectTypeDescriptor<TRuntimeType>>> configureFactory)
16+
=> TryAdd(key, typeof(TRuntimeType), configureFactory);
17+
18+
public static void TryAdd<TRuntimeType>(
19+
string key,
20+
Func<Action<IInterfaceTypeDescriptor<TRuntimeType>>> configureFactory)
21+
=> TryAdd(key, typeof(TRuntimeType), configureFactory);
22+
23+
private static void TryAdd(string key, Type runtimeType, Func<object> configureFactory)
24+
{
25+
lock (_sync)
26+
{
27+
if (!_created.Add(key))
28+
{
29+
return;
30+
}
31+
32+
if (!_configurations.TryGetValue(runtimeType, out var list))
33+
{
34+
list = new List<object>();
35+
_configurations[runtimeType] = list;
36+
}
37+
38+
list.Add(configureFactory());
39+
}
40+
}
41+
42+
internal static void Apply<TDescriptor>(
43+
Type runtimeType,
44+
TDescriptor descriptor)
45+
where TDescriptor : IDescriptor
46+
{
47+
if (_configurations.TryGetValue(runtimeType, out var list))
48+
{
49+
foreach (var item in list)
50+
{
51+
if (item is Func<Action<TDescriptor>> factory)
52+
{
53+
factory()(descriptor);
54+
}
55+
}
56+
}
57+
}
58+
}

src/HotChocolate/Core/src/Types/Types/InterfaceType~1.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ protected override InterfaceTypeDefinition CreateDefinition(ITypeDiscoveryContex
2424
_configure!(descriptor);
2525
_configure = null;
2626

27+
TypeConfiguration.Apply(typeof(T), descriptor);
28+
2729
return descriptor.CreateDefinition();
2830
}
2931

src/HotChocolate/Core/src/Types/Types/ObjectType~1.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ protected override ObjectTypeDefinition CreateDefinition(
4949
_configure!(descriptor);
5050
_configure = null;
5151

52+
TypeConfiguration.Apply<IObjectTypeDescriptor<T>>(typeof(T), descriptor);
53+
5254
return descriptor.CreateDefinition();
5355
}
5456

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Generate_Query_Resolvers
2+
3+
```csharp
4+
// <auto-generated/>
5+
6+
#nullable enable
7+
#pragma warning disable
8+
9+
using System;
10+
using System.Runtime.CompilerServices;
11+
using HotChocolate;
12+
using HotChocolate.Types;
13+
using HotChocolate.Execution.Configuration;
14+
15+
namespace Microsoft.Extensions.DependencyInjection
16+
{
17+
public static partial class TestsTypesRequestExecutorBuilderExtensions
18+
{
19+
public static IRequestExecutorBuilder AddTestsTypes(this IRequestExecutorBuilder builder)
20+
{
21+
builder.AddTypeExtension(typeof(global::TestNamespace.Query));
22+
builder.ConfigureSchema(
23+
b => b.TryAddRootType(
24+
() => new global::HotChocolate.Types.ObjectType(
25+
d => d.Name(global::HotChocolate.Types.OperationTypeNames.Query)),
26+
HotChocolate.Language.OperationType.Query));
27+
return builder;
28+
}
29+
}
30+
}
31+
32+
```

0 commit comments

Comments
 (0)