Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,7 @@ public static IRequestExecutorBuilder AddHttpRequestInterceptor<T>(

return builder.ConfigureSchemaServices(s => s
.RemoveAll<IHttpRequestInterceptor>()
.AddSingleton<IHttpRequestInterceptor, T>(sp =>
ActivatorUtilities.GetServiceOrCreateInstance<T>(sp.GetCombinedServices())));
.AddSingleton<IHttpRequestInterceptor, T>());
}

/// <summary>
Expand Down Expand Up @@ -60,7 +59,7 @@ public static IRequestExecutorBuilder AddHttpRequestInterceptor<T>(

return builder.ConfigureSchemaServices(s => s
.RemoveAll<IHttpRequestInterceptor>()
.AddSingleton<IHttpRequestInterceptor, T>(sp => factory(sp.GetCombinedServices())));
.AddSingleton<IHttpRequestInterceptor, T>(factory));
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,7 @@ public static IRequestExecutorBuilder AddSocketSessionInterceptor<T>(
where T : class, ISocketSessionInterceptor =>
builder.ConfigureSchemaServices(s => s
.RemoveAll<ISocketSessionInterceptor>()
.AddSingleton<ISocketSessionInterceptor, T>(
sp => ActivatorUtilities.GetServiceOrCreateInstance<T>(sp.GetCombinedServices())));
.AddSingleton<ISocketSessionInterceptor, T>());

/// <summary>
/// Adds an interceptor for GraphQL socket sessions to the GraphQL configuration.
Expand All @@ -52,7 +51,7 @@ public static IRequestExecutorBuilder AddSocketSessionInterceptor<T>(
where T : class, ISocketSessionInterceptor =>
builder.ConfigureSchemaServices(s => s
.RemoveAll<ISocketSessionInterceptor>()
.AddSingleton<ISocketSessionInterceptor, T>(sp => factory(sp.GetCombinedServices())));
.AddSingleton<ISocketSessionInterceptor, T>(factory));

private static IRequestExecutorBuilder AddSubscriptionServices(
this IRequestExecutorBuilder builder)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,51 +72,4 @@ public static IServiceProvider GetRootServiceProvider(this Schema schema)
/// </returns>
public static IServiceProvider GetRootServiceProvider(this IServiceProvider services)
=> services.GetRequiredService<IRootServiceProviderAccessor>().ServiceProvider;

/// <summary>
/// Gets a service from the root service provider.
/// </summary>
/// <typeparam name="T">
/// The type of the service to get.
/// </typeparam>
/// <param name="services">
/// The schema services.
/// </param>
/// <returns>
/// The service.
/// </returns>
[Obsolete("Use GetRootServiceProvider instead.")]
public static T GetApplicationService<T>(this IServiceProvider services) where T : notnull
=> services.GetApplicationServices().GetRequiredService<T>();

/// <summary>
/// Gets the root service provider from the schema services. This allows
/// schema services to access application level services.
/// </summary>
/// <param name="services">
/// The schema services.
/// </param>
/// <returns>
/// The root service provider.
/// </returns>
[Obsolete("Use GetRootServiceProvider instead.")]
public static IServiceProvider GetApplicationServices(this IServiceProvider services)
=> services.GetRootServiceProvider();

/// <summary>
/// Gets a service provided that represents the combined services from the schema services
/// and application services.
/// </summary>
/// <param name="services">
/// The schema services.
/// </param>
/// <returns>
/// The service.
/// </returns>
public static IServiceProvider GetCombinedServices(this IServiceProvider services)
=> services is CombinedServiceProvider combined
? combined
: new CombinedServiceProvider(
services.GetRootServiceProvider(),
services);
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,7 @@ public static IRequestExecutorBuilder AddErrorFilter<T>(
ArgumentNullException.ThrowIfNull(factory);

return builder.ConfigureSchemaServices(
s => s.AddSingleton<IErrorFilter, T>(
sp => factory(sp.GetCombinedServices())));
s => s.AddSingleton<IErrorFilter, T>(factory));
}

public static IRequestExecutorBuilder AddErrorFilter<T>(
Expand All @@ -42,8 +41,7 @@ public static IRequestExecutorBuilder AddErrorFilter<T>(

builder.Services.TryAddSingleton<T>();
return builder.ConfigureSchemaServices(
s => s.AddSingleton<IErrorFilter, T>(
sp => sp.GetRootServiceProvider().GetRequiredService<T>()));
s => s.AddSingleton<IErrorFilter, T>());
}

public static IServiceCollection AddErrorFilter(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,26 +17,37 @@ public static IRequestExecutorBuilder AddDiagnosticEventListener<T>(

if (typeof(IExecutionDiagnosticEventListener).IsAssignableFrom(typeof(T)))
{
builder.Services.TryAddSingleton<T>();
builder.ConfigureSchemaServices(
s => s.AddSingleton(
sp => (IExecutionDiagnosticEventListener)sp.GetRootServiceProvider().GetRequiredService<T>()));
static s =>
{
s.TryAddSingleton<T>();
s.AddSingleton(static sp => (IExecutionDiagnosticEventListener)sp.GetRequiredService<T>());
});
}
else if (typeof(IDataLoaderDiagnosticEventListener).IsAssignableFrom(typeof(T)))
{
builder.Services.TryAddSingleton<T>();
builder.Services.AddSingleton(s => (IDataLoaderDiagnosticEventListener)s.GetRequiredService<T>());
builder.Services.AddSingleton(
static s => (IDataLoaderDiagnosticEventListener)s.GetRequiredService<T>());
}
else if (typeof(T).IsDefined(typeof(DiagnosticEventSourceAttribute), true))
{
builder.Services.TryAddSingleton<T>();
var attribute = (DiagnosticEventSourceAttribute)typeof(T).GetCustomAttributes(typeof(DiagnosticEventSourceAttribute), true).First();
var listener = attribute.Listener;

builder.ConfigureSchemaServices(static s =>
if (attribute.IsSchemaService)
{
builder.ConfigureSchemaServices(s =>
{
s.TryAddSingleton<T>();
s.AddSingleton(listener, sp => sp.GetRequiredService<T>());
});
}
else
{
var attribute = typeof(T).GetCustomAttributes(typeof(DiagnosticEventSourceAttribute), true).First();
var listener = ((DiagnosticEventSourceAttribute)attribute).Listener;
s.AddSingleton(listener, sp => sp.GetRootServiceProvider().GetRequiredService<T>());
});
builder.Services.TryAddSingleton<T>();
builder.Services.AddSingleton(listener, sp => sp.GetRequiredService<T>());
}
}
else
{
Expand All @@ -48,43 +59,34 @@ public static IRequestExecutorBuilder AddDiagnosticEventListener<T>(

public static IRequestExecutorBuilder AddDiagnosticEventListener<T>(
this IRequestExecutorBuilder builder,
Func<IServiceProvider, T> diagnosticEventListener)
Func<IServiceProvider, T> factory)
where T : class
{
ArgumentNullException.ThrowIfNull(builder);
ArgumentNullException.ThrowIfNull(diagnosticEventListener);
ArgumentNullException.ThrowIfNull(factory);

if (typeof(IExecutionDiagnosticEventListener).IsAssignableFrom(typeof(T)))
{
builder.ConfigureSchemaServices(
s => s.AddSingleton(
sp => (IExecutionDiagnosticEventListener)diagnosticEventListener(
sp.GetCombinedServices())));
s => s.AddSingleton(sp => (IExecutionDiagnosticEventListener)factory(sp)));
}
else if (typeof(IDataLoaderDiagnosticEventListener).IsAssignableFrom(typeof(T)))
{
builder.Services.AddSingleton(
s => (IDataLoaderDiagnosticEventListener)diagnosticEventListener(s));
s => (IDataLoaderDiagnosticEventListener)factory(s));
}
else if (typeof(T).IsDefined(typeof(DiagnosticEventSourceAttribute), true))
{
var attribute =
(DiagnosticEventSourceAttribute)typeof(T)
.GetCustomAttributes(typeof(DiagnosticEventSourceAttribute), true)
.First();
var attribute = (DiagnosticEventSourceAttribute)typeof(T).GetCustomAttributes(typeof(DiagnosticEventSourceAttribute), true).First();
var listener = attribute.Listener;

if (attribute.IsSchemaService)
{
builder.ConfigureSchemaServices(s =>
{
var listener = attribute.Listener;
s.AddSingleton(listener, sp => diagnosticEventListener(sp.GetCombinedServices()));
});
builder.ConfigureSchemaServices(s => s.AddSingleton(listener, factory));
}
else
{
var listener = attribute.Listener;
builder.Services.AddSingleton(listener, diagnosticEventListener);
builder.Services.AddSingleton(listener, factory);
}
}
else
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,7 @@ public static IRequestExecutorBuilder AddOperationCompilerOptimizer<T>(
ArgumentNullException.ThrowIfNull(builder);

builder.ConfigureSchemaServices(
sc => sc.AddSingleton<IOperationCompilerOptimizer>(
sp => factory(sp.GetCombinedServices())));
sc => sc.AddSingleton<IOperationCompilerOptimizer>(factory));
return builder;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,22 @@ public static IRequestExecutorBuilder AddScopedServiceInitializer<TService>(
builder.Services.AddSingleton<IServiceScopeInitializer>(new DelegateServiceInitializer<TService>(initializer));
return builder;
}

/// <summary>
/// Resolves an instance of <typeparamref name="TService"/> from the application
/// service provider and makes it available as a Singleton through the schema
/// service provider.
/// </summary>
/// <typeparam name="TService">
/// The type of service.
/// </typeparam>
public static IRequestExecutorBuilder AddApplicationService<TService>(
this IRequestExecutorBuilder builder)
where TService : class
{
return builder.ConfigureSchemaServices(
static (sp, sc) => sc.AddSingleton(sp.GetRequiredService<TService>()));
}
}

file sealed class DelegateServiceInitializer<TService>(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,10 @@ public static IRequestExecutorBuilder AddTransactionScopeHandler<T>(

return ConfigureSchemaServices(
builder,
services =>
static services =>
{
// we remove all handlers from the schema DI
services.RemoveAll(typeof(ITransactionScopeHandler));

// and then reference the transaction scope handler from the global DI.
services.AddSingleton<ITransactionScopeHandler>(
s => s.GetRootServiceProvider().GetRequiredService<T>());
services.RemoveAll<ITransactionScopeHandler>();
services.AddSingleton<ITransactionScopeHandler, T>();
});
}

Expand All @@ -50,7 +46,7 @@ public static IRequestExecutorBuilder AddTransactionScopeHandler<T>(
/// <param name="builder">
/// The request executor builder.
/// </param>
/// <param name="create">
/// <param name="factory">
/// A factory to create the transaction scope.
/// </param>
/// <returns>
Expand All @@ -59,17 +55,17 @@ public static IRequestExecutorBuilder AddTransactionScopeHandler<T>(
/// <exception cref="ArgumentNullException"></exception>
public static IRequestExecutorBuilder AddTransactionScopeHandler(
this IRequestExecutorBuilder builder,
Func<IServiceProvider, ITransactionScopeHandler> create)
Func<IServiceProvider, ITransactionScopeHandler> factory)
{
ArgumentNullException.ThrowIfNull(builder);
ArgumentNullException.ThrowIfNull(create);
ArgumentNullException.ThrowIfNull(factory);

return ConfigureSchemaServices(
builder,
services =>
{
services.RemoveAll(typeof(ITransactionScopeHandler));
services.AddSingleton(sp => create(sp.GetCombinedServices()));
services.RemoveAll<ITransactionScopeHandler>();
services.AddSingleton(factory);
});
}

Expand Down Expand Up @@ -101,10 +97,7 @@ internal static IRequestExecutorBuilder TryAddNoOpTransactionScopeHandler(

return ConfigureSchemaServices(
builder,
services =>
{
services.TryAddSingleton<ITransactionScopeHandler>(
sp => sp.GetRootServiceProvider().GetRequiredService<NoOpTransactionScopeHandler>());
});
static services =>
services.TryAddSingleton<ITransactionScopeHandler, NoOpTransactionScopeHandler>());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ public TypeSystemObject CreateInstance(Type namedSchemaType)
{
try
{
return (TypeSystemObject)ActivatorUtilities.CreateInstance(_combinedServices, namedSchemaType);
var services = _applicationServices ?? _schemaServices;

return (TypeSystemObject)ActivatorUtilities.CreateInstance(services, namedSchemaType);
}
catch (Exception ex)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using HotChocolate.Internal;
using HotChocolate.Types;
using HotChocolate.Types.Descriptors;
using HotChocolate.Utilities;

namespace HotChocolate.Configuration;

Expand All @@ -15,7 +14,6 @@ internal sealed partial class TypeRegistrar : ITypeRegistrar
private readonly TypeInterceptor _interceptor;
private readonly IServiceProvider _schemaServices;
private readonly IServiceProvider? _applicationServices;
private readonly IServiceProvider _combinedServices;

public TypeRegistrar(IDescriptorContext context,
TypeRegistry typeRegistry,
Expand All @@ -32,10 +30,6 @@ public TypeRegistrar(IDescriptorContext context,
throw new ArgumentNullException(nameof(typeInterceptor));
_schemaServices = context.Services;
_applicationServices = context.Services.GetService<IRootServiceProviderAccessor>()?.ServiceProvider;

_combinedServices = _applicationServices is null
? _schemaServices
: new CombinedServiceProvider(_schemaServices, _applicationServices);
}

public ISet<string> Scalars { get; } = new HashSet<string>();
Expand Down
2 changes: 1 addition & 1 deletion src/HotChocolate/Core/src/Types/SchemaBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ public ISchemaBuilder AddServices(IServiceProvider services)
{
ArgumentNullException.ThrowIfNull(services);

_services = _services is null ? services : new CombinedServiceProvider(_services, services);
_services = services;

return this;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using HotChocolate.Language;
using HotChocolate.Utilities;
using Microsoft.Extensions.DependencyInjection;

namespace HotChocolate.Execution;

Expand Down Expand Up @@ -246,9 +247,9 @@ public void BuildRequest_QueryAndServices_RequestIsCreated()
OperationRequestBuilder.New()
.SetDocument("{ foo }")
.SetServices(
new DictionaryServiceProvider(
service.GetType(),
service))
new ServiceCollection()
.AddSingleton(service.GetType(), service)
.BuildServiceProvider())
.Build();

// assert
Expand All @@ -268,7 +269,7 @@ public void BuildRequest_SetAll_RequestIsCreated()
.SetOperationName("bar")
.AddGlobalState("one", "foo")
.SetVariableValues(new Dictionary<string, object?> { { "two", "bar" } })
.SetServices(new DictionaryServiceProvider(service.GetType(), service))
.SetServices(new ServiceCollection().AddSingleton(service.GetType(), service).BuildServiceProvider())
.Build();

// assert
Expand Down
Loading
Loading