IOC: scoped/on-demand services (#1120)

This commit is contained in:
goat 2023-05-21 22:43:28 +02:00 committed by GitHub
parent ca8a05b672
commit daa9f72218
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 309 additions and 62 deletions

View file

@ -65,6 +65,11 @@ internal static class ServiceManager
/// </summary>
BlockingEarlyLoadedService = 1 << 2,
/// <summary>
/// Service that is only instantiable via scopes.
/// </summary>
ScopedService = 1 << 3,
/// <summary>
/// Service that is loaded automatically when the game starts, synchronously or asynchronously.
/// </summary>
@ -133,10 +138,12 @@ internal static class ServiceManager
foreach (var serviceType in Assembly.GetExecutingAssembly().GetTypes())
{
var serviceKind = serviceType.GetServiceKind();
if (serviceKind == ServiceKind.None)
if (serviceKind is ServiceKind.None or ServiceKind.ScopedService)
continue;
Debug.Assert(!serviceKind.HasFlag(ServiceKind.ManualService), "Regular services should never end up here");
Debug.Assert(
!serviceKind.HasFlag(ServiceKind.ManualService) && !serviceKind.HasFlag(ServiceKind.ScopedService),
"Regular and scoped services should never be loaded early");
var genericWrappedServiceType = typeof(Service<>).MakeGenericType(serviceType);
@ -389,6 +396,9 @@ internal static class ServiceManager
if (attr.IsAssignableTo(typeof(EarlyLoadedService)))
return ServiceKind.EarlyLoadedService;
if (attr.IsAssignableTo(typeof(ScopedService)))
return ServiceKind.ScopedService;
return ServiceKind.ManualService;
}
@ -435,6 +445,15 @@ internal static class ServiceManager
{
}
/// <summary>
/// Indicates that the class is a service that will be created specifically for a
/// service scope, and that it cannot be created outside of a scope.
/// </summary>
[AttributeUsage(AttributeTargets.Class)]
public class ScopedService : Service
{
}
/// <summary>
/// Indicates that the method should be called when the services given in the constructor are ready.
/// </summary>