-
-
Notifications
You must be signed in to change notification settings - Fork 744
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
fd1e64e
commit dfcd21a
Showing
15 changed files
with
267 additions
and
37 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
55 changes: 55 additions & 0 deletions
55
...olate/Core/src/Execution/DependencyInjection/RequestExecutorBuilderExtensions.Services.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,55 @@ | ||
using System; | ||
using HotChocolate.Execution.Configuration; | ||
using HotChocolate.Resolvers; | ||
|
||
// ReSharper disable once CheckNamespace | ||
namespace Microsoft.Extensions.DependencyInjection; | ||
|
||
public static partial class RequestExecutorBuilderExtensions | ||
{ | ||
/// <summary> | ||
/// Adds a initializer to copy state between a request scoped service instance and | ||
/// a resolver scoped service instance. | ||
/// </summary> | ||
/// <param name="builder"> | ||
/// The request executor builder. | ||
/// </param> | ||
/// <param name="initializer"> | ||
/// The initializer that is used to initialize the service scope. | ||
/// </param> | ||
/// <typeparam name="TService"> | ||
/// The type of the service that shall be initialized. | ||
/// </typeparam> | ||
/// <returns></returns> | ||
/// <exception cref="ArgumentNullException"> | ||
/// The <paramref name="builder"/> is <c>null</c>. | ||
/// </exception> | ||
public static IRequestExecutorBuilder AddScopedServiceInitializer<TService>( | ||
this IRequestExecutorBuilder builder, | ||
Action<TService, TService> initializer) | ||
{ | ||
if (builder == null) | ||
{ | ||
throw new ArgumentNullException(nameof(builder)); | ||
} | ||
|
||
if (initializer == null) | ||
{ | ||
throw new ArgumentNullException(nameof(initializer)); | ||
} | ||
|
||
builder.Services.AddSingleton<IServiceScopeInitializer>(new DelegateServiceInitializer<TService>(initializer)); | ||
return builder; | ||
} | ||
} | ||
|
||
file sealed class DelegateServiceInitializer<TService>( | ||
Action<TService, TService> initializer) | ||
: ServiceInitializer<TService> | ||
{ | ||
private readonly Action<TService, TService> _initializer = initializer ?? | ||
throw new ArgumentNullException(nameof(initializer)); | ||
|
||
protected override void Initialize(TService requestScopeService, TService resolverScopeService) | ||
=> _initializer(requestScopeService, resolverScopeService); | ||
} |
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
59 changes: 59 additions & 0 deletions
59
src/HotChocolate/Core/src/Types/Resolvers/AggregateServiceScopeInitializer.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,59 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Runtime.CompilerServices; | ||
using System.Runtime.InteropServices; | ||
|
||
namespace HotChocolate.Resolvers; | ||
|
||
internal sealed class AggregateServiceScopeInitializer : IServiceScopeInitializer | ||
{ | ||
private readonly IServiceScopeInitializer[] _initializers; | ||
|
||
public AggregateServiceScopeInitializer(IEnumerable<IServiceScopeInitializer> serviceScopeInitializers) | ||
{ | ||
if (serviceScopeInitializers == null) | ||
{ | ||
throw new ArgumentNullException(nameof(serviceScopeInitializers)); | ||
} | ||
|
||
_initializers = serviceScopeInitializers.ToArray(); | ||
} | ||
|
||
public void Initialize(IServiceProvider requestScope, IServiceProvider resolverScope) | ||
{ | ||
switch (_initializers.Length) | ||
{ | ||
case 0: | ||
return; | ||
|
||
case 1: | ||
_initializers[0].Initialize(requestScope, resolverScope); | ||
break; | ||
|
||
case 2: | ||
_initializers[0].Initialize(requestScope, resolverScope); | ||
_initializers[1].Initialize(requestScope, resolverScope); | ||
break; | ||
|
||
case 3: | ||
_initializers[0].Initialize(requestScope, resolverScope); | ||
_initializers[1].Initialize(requestScope, resolverScope); | ||
_initializers[2].Initialize(requestScope, resolverScope); | ||
break; | ||
|
||
default: | ||
{ | ||
ref var start = ref MemoryMarshal.GetReference(_initializers.AsSpan()); | ||
ref var end = ref Unsafe.Add(ref start, _initializers.Length); | ||
|
||
while (Unsafe.IsAddressLessThan(ref start, ref end)) | ||
{ | ||
start.Initialize(requestScope, resolverScope); | ||
start = ref Unsafe.Add(ref start, 1); | ||
} | ||
break; | ||
} | ||
} | ||
} | ||
} |
20 changes: 20 additions & 0 deletions
20
src/HotChocolate/Core/src/Types/Resolvers/IServiceScopeInitializer.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,20 @@ | ||
using System; | ||
|
||
namespace HotChocolate.Resolvers; | ||
|
||
/// <summary> | ||
/// Implement this to copy state from the requestScope to the resolver scope. | ||
/// </summary> | ||
public interface IServiceScopeInitializer | ||
{ | ||
/// <summary> | ||
/// Initializes the resolver scope with state from the request scope. | ||
/// </summary> | ||
/// <param name="requestScope"> | ||
/// The request scope from which state shall be copied. | ||
/// </param> | ||
/// <param name="resolverScope"> | ||
/// The resolver scope to which state shall be copied. | ||
/// </param> | ||
void Initialize(IServiceProvider requestScope, IServiceProvider resolverScope); | ||
} |
18 changes: 18 additions & 0 deletions
18
src/HotChocolate/Core/src/Types/Resolvers/ServiceInitializer.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,18 @@ | ||
using System; | ||
|
||
namespace HotChocolate.Resolvers; | ||
|
||
/// <summary> | ||
/// This is a base class allows to copy state from a single service of the | ||
/// request scope to the same service in the resolver scope. | ||
/// </summary> | ||
/// <typeparam name="TService"> | ||
/// The service type for which state shall be copied. | ||
/// </typeparam> | ||
public abstract class ServiceInitializer<TService> : IServiceScopeInitializer | ||
{ | ||
public void Initialize(IServiceProvider requestScope, IServiceProvider resolverScope) | ||
=> Initialize(requestScope.GetRequiredService<TService>(), resolverScope.GetRequiredService<TService>()); | ||
|
||
protected abstract void Initialize(TService requestScopeService, TService resolverScopeService); | ||
} |
28 changes: 28 additions & 0 deletions
28
...st/Execution.Tests/DependencyInjection/RequestExecutorBuilderExtensions_Services.Tests.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 @@ | ||
using HotChocolate.Execution.Configuration; | ||
using Microsoft.Extensions.DependencyInjection; | ||
using Moq; | ||
|
||
namespace HotChocolate.Execution.DependencyInjection; | ||
|
||
public class RequestExecutorBuilderExtensionsServicesTests | ||
{ | ||
[Fact] | ||
public void AddScopedServiceInitializer_1_Builder_Is_Null() | ||
{ | ||
void Fail() => RequestExecutorBuilderExtensions | ||
.AddScopedServiceInitializer<string>(null!, (_, _) => { }); | ||
|
||
Assert.Throws<ArgumentNullException>(Fail); | ||
} | ||
|
||
[Fact] | ||
public void AddScopedServiceInitializer_1_Initializer_Is_Null() | ||
{ | ||
var mock = new Mock<IRequestExecutorBuilder>(); | ||
|
||
void Fail() => RequestExecutorBuilderExtensions | ||
.AddScopedServiceInitializer<string>(mock.Object, null!); | ||
|
||
Assert.Throws<ArgumentNullException>(Fail); | ||
} | ||
} |
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
Oops, something went wrong.