using System; using System.Reflection; using Godot; using Microsoft.Extensions.DependencyInjection; using OwofGames.GodotLume; namespace GodotHostTest.GodotDI; [Icon("res://addons/GodotDI/ServiceSource.svg")] public partial class ServiceSource : Node { [Export] private string _serviceScope = typeof(RootScope).AssemblyQualifiedName!; [Export] protected Node?[] InjectedNodes = []; internal void ResolveInjectedNodes(IServiceProvider serviceProvider) { // if this service source must also act as a scope, create the scope and use its service provider if (_serviceScope != "") { serviceProvider = serviceProvider .CreateScope() .ServiceProvider; } // resolve the injected nodes against the chosen service provider // TODO: move to source generator, make it the only way for injection foreach (var node in InjectedNodes) { if (node == null) continue; var nodeType = node.GetType(); foreach (var field in nodeType .GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) { if (field.GetCustomAttribute() == null) continue; var fieldType = field.FieldType; var service = serviceProvider.GetRequiredService(fieldType); field.SetValue(node, service); } foreach (var method in nodeType.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) { if (method.GetCustomAttribute() == null) continue; var parameters = method.GetParameters(); var values = new object?[parameters.Length]; var i = 0; foreach (var parameter in parameters) { var parameterType = parameter.ParameterType; var service = serviceProvider.GetRequiredService(parameterType); values[i++] = service; } method.Invoke(node, values); } } } }