using System; using System.Linq; using Godot; using Microsoft.Extensions.Logging; using OwofGames.AetherBind; using OwofGames.GodotLume; namespace GodotHostTest.AetherBind; [Icon("res://addons/AetherBind/ServiceSource.svg")] public partial class ServiceSource : Node { private static readonly string RootScopeQualifiedName = typeof(RootScope).AssemblyQualifiedName!; [Export] protected Node?[] InjectedNodes = []; [Export] private string _serviceScope = RootScopeQualifiedName; internal void ResolveInjectedNodes(IProvider provider, Delegate? onScopeCreated) { var logger = provider.Get>(); // if this service source must also act as a scope, create the scope and use its service provider if (_serviceScope != RootScopeQualifiedName) { // create the scoped provider var serviceScope = ScopeTypesAndNames.GetType(_serviceScope); provider = provider.GetScopedProvider(serviceScope); // invoke onScopeCreated, if present if (onScopeCreated != null) { var parameters = onScopeCreated.Method .GetParameters() .Select(parameterInfo => provider.Get(parameterInfo.ParameterType)) .ToArray(); onScopeCreated.DynamicInvoke(parameters); } OnScopeCreated(provider); } else if (onScopeCreated != null) { logger.LogWarning("onScopeCreated passed during instantiation, but no scoped provider was created."); } // resolve the injected nodes against the chosen service provider foreach (var node in InjectedNodes) { if (node == null) continue; logger.LogTrace("Injecting {Node}.", node.Name); if (node is IInjectable injectable) { injectable.Inject(provider); } } } // TODO: also add source generator to mark methods in derived classes with [OnScopeCreated] and perform parameter injection protected virtual void OnScopeCreated(IProvider serviceProvider) { } }