// MIT License - Copyright (c) 2025 wallstop
// Full license text: https://github.com/wallstop/unity-helpers/blob/main/LICENSE
#if REFLEX_PRESENT
namespace WallstopStudios.UnityHelpers.Integrations.Reflex
{
using System;
using System.Collections.Generic;
using global::Reflex.Core;
using global::Reflex.Injectors;
using UnityEngine;
using WallstopStudios.UnityHelpers.Core.Attributes;
using WallstopStudios.UnityHelpers.Utils;
///
/// Extension methods that bridge Reflex containers with relational component assignment.
///
public static class ContainerRelationalExtensions
{
///
/// Injects a component using Reflex and assigns its relational fields.
///
/// Component type.
/// Reflex container.
/// Component instance to inject and hydrate.
/// The injected component instance.
public static T InjectWithRelations(this Container container, T component)
where T : Component
{
if (component == null)
{
return null;
}
if (container != null)
{
AttributeInjector.Inject(component, container);
}
container.AssignRelationalComponents(component);
return component;
}
///
/// Assigns relational component fields on the supplied component.
///
/// Reflex container.
/// Component to hydrate.
public static void AssignRelationalComponents(this Container container, Component component)
{
if (component == null)
{
return;
}
IRelationalComponentAssigner assigner = ResolveAssigner(container);
if (assigner != null)
{
assigner.Assign(component);
return;
}
component.AssignRelationalComponents();
}
///
/// Assigns relational component fields across a GameObject hierarchy.
///
/// Reflex container.
/// Hierarchy root.
///
/// When true, includes inactive children during assignment.
///
public static void AssignRelationalHierarchy(
this Container container,
GameObject root,
bool includeInactiveChildren = true
)
{
if (root == null)
{
return;
}
IRelationalComponentAssigner assigner = ResolveAssigner(container);
if (assigner != null)
{
assigner.AssignHierarchy(root, includeInactiveChildren);
return;
}
using PooledResource> pooledComponents = Buffers.List.Get(
out List components
);
root.GetComponentsInChildren(includeInactiveChildren, components);
for (int i = 0; i < components.Count; i++)
{
Component component = components[i];
if (component == null)
{
continue;
}
component.AssignRelationalComponents();
}
}
///
/// Instantiates a component prefab, injects it, and assigns relational fields.
///
/// Component type contained by the prefab.
/// Reflex container.
/// Component prefab.
/// Optional parent transform.
/// The instantiated and hydrated component.
public static T InstantiateComponentWithRelations(
this Container container,
T prefab,
Transform parent = null
)
where T : Component
{
if (prefab == null)
{
throw new ArgumentNullException(nameof(prefab));
}
T instance = UnityEngine.Object.Instantiate(prefab, parent);
return container.InjectWithRelations(instance);
}
///
/// Instantiates a GameObject prefab, injects the hierarchy, and assigns relational fields.
///
/// Reflex container.
/// GameObject prefab.
/// Optional parent transform.
///
/// When true, includes inactive children during relational assignment.
///
/// The instantiated GameObject.
public static GameObject InstantiateGameObjectWithRelations(
this Container container,
GameObject prefab,
Transform parent = null,
bool includeInactiveChildren = true
)
{
if (prefab == null)
{
throw new ArgumentNullException(nameof(prefab));
}
GameObject instance = UnityEngine.Object.Instantiate(prefab, parent);
container.InjectGameObjectWithRelations(instance, includeInactiveChildren);
return instance;
}
///
/// Injects all components in a hierarchy and assigns relational fields.
///
/// Reflex container.
/// Root GameObject.
///
/// When true, includes inactive children during relational assignment.
///
public static void InjectGameObjectWithRelations(
this Container container,
GameObject root,
bool includeInactiveChildren = true
)
{
if (root == null)
{
return;
}
if (container != null)
{
GameObjectInjector.InjectRecursive(root, container);
}
container.AssignRelationalHierarchy(root, includeInactiveChildren);
}
private static IRelationalComponentAssigner ResolveAssigner(Container container)
{
if (container == null)
{
return null;
}
if (container.HasBinding())
{
return container.Resolve();
}
return null;
}
}
}
#endif