Я решил сделать свой собственный легкий DI-контейнер.
Я знаю о Zenject, et c. Я хотел очень легкий аналог.
Меня беспокоит несколько вещей:
1) Правильно ли использовать struct вместо класса для ссылки в этом контексте?
2) каждый раз, когда вы получаете доступ к _player.Reference, происходит проверка на ноль (в UnityEngine. После уничтожения Объекта не равняется нулю, поэтому используйте SafeIsUnityNull)
3) Двойная точка. Можно ли перегрузить оператор, чтобы вместо _player.Reference.AAAAAAAAAAAAA();
он работал _player.AAAAAAAAAAAAA();
??
Сам контейнер:
public static class DIContainer
{
private static readonly Dictionary<System.Type, Object> _references = new Dictionary<System.Type, Object>();
public static void Bind<T>(T value) where T : Object
{
_references[typeof(T)] = value;
}
public static T Resolve<T>() where T : Object
{
if (_references.TryGetValue(typeof(T), out Object value))
return (T)value;
throw new System.InvalidCastException($"DIContainer: invalid resolve object {typeof(T)}");
}
}
Ссылка на поле:
public struct DIReference<T> where T : Object
{
private T _reference;
public T Reference => !_reference.SafeIsUnityNull() ? _reference : _reference = DIContainer.Resolve<T>();
}
Установщик:
public abstract class SceneInstaller : MonoBehaviour
{
private void Awake() => InstallBindings();
protected abstract void InstallBindings();
}
public class LevelInstaller : SceneInstaller
{
}
Использование
Связывание:
[SerializeField] private PlayerController _player;
protected override void InstallBindings()
{
DIContainer.Bind(_player);
}
Ссылка:
public class Test
{
private DIReference<PlayerController> _player;
private void Foo()
{
_player.Reference.AAAAAAAAAAAAA();
}
}