using System; using System.Linq; using Godot; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using OwofGames.GodotHost; using OwofGames.GodotLume.Microsoft.DependencyInjection; namespace GodotHostTest.GodotDI; /// /// The base class for a root scope. Implement this class and its abstract methods to kick off the DI system. /// public abstract partial class RootServiceSource : ServiceSource, ISceneInstantiator { private Host? _host; private Host Host { get => _host ?? throw new InvalidOperationException( "Some method of RootScope has been invoked before it entered the tree"); set => _host = value; } private ILogger? _logger; private ILogger Logger => _logger ??= Host.GetLogger(); public override void _EnterTree() { // create the host Host = new HostBuilder() .SetServiceCollectionBuilder(InnerConfigure) .SetServiceProviderFactory(new LumeServiceProviderFactory()) .Build(); // resolve nodes ResolveInjectedNodes(Host.ServiceProvider); } private void InnerConfigure(IServiceCollection serviceCollection) { serviceCollection.AddSingleton(this); Configure(serviceCollection); } /// /// Configure the service collection by adding the registrations your game needs. /// /// The service collection to enrich. protected abstract void Configure(IServiceCollection serviceCollection); /// public Node Instantiate(PackedScene packedScene) { var node = packedScene.Instantiate(); var scope = node.GetChildren().OfType().SingleOrDefault(); if (scope == null) { Logger.LogDebug( "Instantiated the scene {PackedSceneName} through ISceneInstantiator.Instantiate, but no scope found.", packedScene.GetName()); } else { scope.ResolveInjectedNodes(Host.ServiceProvider); } return node; } /// public T Instantiate(PackedScene packedScene) where T : Node { return (T)Instantiate(packedScene); } }