using System;
using Autofac;
using Autofac.Builder;
using NitroxModel.DataStructures.Util;
namespace NitroxModel.Core;
///
/// Dependency Injection (DI) class for resolving types as defined in the DI registrar, implementing .
///
public static class NitroxServiceLocator
{
private static IContainer DependencyContainer { get; set; }
private static ILifetimeScope CurrentLifetimeScope { get; set; }
public static event EventHandler LifetimeScopeEnded;
public static void InitializeDependencyContainer(params IAutoFacRegistrar[] registrars)
{
ContainerBuilder builder = new();
foreach (IAutoFacRegistrar registrar in registrars)
{
registrar.RegisterDependencies(builder);
}
// IgnoreStartableComponents - Prevents "phantom" executions of the Start() method
// on a MonoBehaviour because someone accidentally did something funky with a DI registration.
DependencyContainer = builder.Build(ContainerBuildOptions.IgnoreStartableComponents);
}
///
/// Starts a new life time scope. A single instance per registered service will be returned while this scope is active.
/// Services can scoped to this life time using .
///
///
/// A life time scope should be created when the game leaves the main menu and loads a level with multiplayer.
/// It should end when the game process unloads the level (e.g. player returns to the main menu).
///
public static void BeginNewLifetimeScope()
{
if (DependencyContainer == null)
{
throw new InvalidOperationException("You must install an Autofac container before initializing a new lifetime scope.");
}
CurrentLifetimeScope?.Dispose();
CurrentLifetimeScope = DependencyContainer.BeginLifetimeScope();
}
///
/// Ends the life time scoped services that were registered using .
///
public static void EndCurrentLifetimeScope()
{
CurrentLifetimeScope?.Dispose();
OnLifetimeScopeEnded();
}
///
/// Only locates the service in the container, pre-lifetime scope.
///
public static T LocateServicePreLifetime()
{
return DependencyContainer.Resolve();
}
///
/// Retrieves a service which was registered into the DI container. Creates a new instance if required.
///
///
/// This method should not be used if the constructor is available for defining a parameter where its type is the service to inject.
/// For Unity monobehaviours the constructor is used by Unity and cannot be used to inject services. In this case, use this method.
///
public static T LocateService()
where T : class
{
CheckServiceResolutionViability();
return CurrentLifetimeScope.Resolve();
}
///
/// Non-generic alternative to .
///
public static object LocateService(Type serviceType)
{
CheckServiceResolutionViability();
return CurrentLifetimeScope.Resolve(serviceType);
}
///
/// Tries to locate the service if it exists. Can return an without a value.
///
/// Type of service to try to locate.
/// Optional that might or might not hold the service instance.
public static Optional LocateOptionalService() where T : class
{
CheckServiceResolutionViability();
return Optional.OfNullable(CurrentLifetimeScope.ResolveOptional());
}
///
/// Tries to locate the service if it exists. Can return an without a value.
///
/// Type of service to try to locate.
/// Optional that might or might not hold the service instance.
public static Optional