using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace QFSW.QC
{
///
/// Prevents the type from being loaded by an InjectionLoader
///
[AttributeUsage(AttributeTargets.Class, Inherited = false)]
public sealed class NoInjectAttribute : Attribute { }
///
/// Loads and instantiates instances of the injectable types.
///
/// The base type for the instances that will be injected.
public class InjectionLoader
{
private Type[] _injectableTypes;
///
/// Retrieves all of the injectable types.
///
/// Forces a reload of the types instead of using the cache.
/// The injectable types.
public Type[] GetInjectableTypes(bool forceReload = false)
{
if (_injectableTypes == null || forceReload)
{
#if UNITY_2019_2_OR_NEWER && UNITY_EDITOR
_injectableTypes = UnityEditor.TypeCache.GetTypesDerivedFrom()
.Where(type => !type.IsAbstract)
.Where(type => !type.IsDefined(typeof(NoInjectAttribute), false))
.ToArray();
#else
_injectableTypes = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(assembly => assembly.GetTypes())
.Where(type => typeof(T).IsAssignableFrom(type))
.Where(type => !type.IsAbstract)
.Where(type => !type.IsDefined(typeof(NoInjectAttribute), false))
.ToArray();
#endif
}
return _injectableTypes;
}
///
/// Creates instances for all of the injectable types available.
///
/// Forces a reload of the types instead of using the cache.
/// The injectable instances.
public IEnumerable GetInjectedInstances(bool forceReload = false)
{
IEnumerable injectableTypes = GetInjectableTypes(forceReload);
return GetInjectedInstances(injectableTypes);
}
///
/// Creates instances from a custom sequence of injectable types.
///
/// The types to create instances for.
/// The injectable instances.
public IEnumerable GetInjectedInstances(IEnumerable injectableTypes)
{
foreach (Type type in injectableTypes)
{
T instance = default;
bool success = false;
try
{
instance = (T)Activator.CreateInstance(type);
success = true;
}
catch (MissingMethodException)
{
Debug.LogError($"Could not load {typeof(T)} {type} as it is missing a public parameterless constructor.");
}
catch (Exception e)
{
Debug.LogException(e);
}
if (success)
{
yield return instance;
}
}
}
}
}