78 lines
3.0 KiB
C#
78 lines
3.0 KiB
C#
using System;
|
|
using Godot;
|
|
using Microsoft.Extensions.Logging;
|
|
using OwofGames.AetherBind;
|
|
using OwofGames.GodotLume;
|
|
|
|
namespace GodotHostTest.AetherBind;
|
|
|
|
/// <summary>
|
|
/// A node that provides injected services to other nodes.
|
|
/// </summary>
|
|
[Icon("res://addons/AetherBind/ServiceSource.svg")]
|
|
public partial class ServiceSource : Node
|
|
{
|
|
private static readonly string RootScopeQualifiedName = typeof(RootScope).AssemblyQualifiedName!;
|
|
|
|
/// <summary>
|
|
/// List of nodes that must be injected. This list will be automatically populated with all nodes in this object's
|
|
/// editor scene that have at least one [Inject] field or method.
|
|
/// </summary>
|
|
[Export] protected Node?[] InjectedNodes = [];
|
|
|
|
/// <summary>
|
|
/// Name of the scope for the services built by this service source.
|
|
/// </summary>
|
|
[Export] private string _serviceScope = RootScopeQualifiedName;
|
|
|
|
/// <summary>
|
|
/// Inject the required services in <see cref="InjectedNodes" />.
|
|
/// </summary>
|
|
/// <param name="provider">The service provider.</param>
|
|
/// <param name="onScopeCreated">A callback method invoked with this scope's provider, if a scope was created.</param>
|
|
internal void ResolveInjectedNodes(IProvider provider, Action<IProvider>? onScopeCreated)
|
|
{
|
|
var logger = provider.Get<ILogger<ServiceSource>>();
|
|
|
|
// 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
|
|
onScopeCreated?.Invoke(provider);
|
|
|
|
// invoke overridden callback
|
|
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
|
|
/// <summary>
|
|
/// This method is invoked as soon as the scope for the services is created, but before the services are injected into
|
|
/// the <see cref="InjectedNodes" />. Override this method in derived classes to perform custom initialization steps
|
|
/// for the services, like setting <see cref="ValueProvider{T}" />s.
|
|
/// </summary>
|
|
/// <param name="serviceProvider">Lume's service provider.</param>
|
|
protected virtual void OnScopeCreated(IProvider serviceProvider)
|
|
{
|
|
}
|
|
} |