8.2 KiB
Auto Injections for DragonECS
Languages: | Русский | English(WIP) |
---|
Расширение призвано сократить объем кода, упростив инъекцию зависимостей, делая их автоматически.
ВАЖНО! Проект в стадии разработки. API может меняться.
Оглавление
Установка
Зависимости
Убедитесь что в проекте установлен фреймворк DragonECS.
-
Unity-модуль
Поддерживается установка в виде Unity-модуля в при помощи добавления git-URL в PackageManager или ручного добавления в Packages/manifest.json
:
https://github.com/DCFApixels/DragonECS-AutoInjections.git
-
В виде исходников
Фреймворк так же может быть добавлен в проект в виде исходников.
Версионирование
В DragonECS применяется следующая семантика версионирования: Открыть
Интеграция
Добавьте вызов метода AutoInject()
для Builder-а пайплайна. Пример:
_pipeline = EcsPipeline.New()
.Inject(world)
.Inject(_timeService)
.Add(new TestSystem())
.Add(new VelocitySystem())
.Add(new ViewSystem())
.AutoInject() // Готово, автоматические внедрения активированы
.BuildAndInit();
Инъекция зависимостей
Атрибут [EcsInject]
убирает необходимость использования интерфейса IEcsInject<T>
, поля помеченные таким атрибутом автоматически подхватят зависимости внедренные в Pipeline. Пример:
[EcsInject] EcsDefaultWorld _world;
Так же можно делать внедрение через свойство или метод
EcsDefaultWorld _world;
//Обязательно наличие set блока.
[EcsInject] EcsDefaultWorld World { set => _world = value; }
//Количество аргументов должно быть равно 1.
[EcsInject] void InjectWorld(EcsDefaultWorld world) => _world = world;
Auto Builder субъектов
Так же AutoInjections упрощает построение субъектов. Для начала наследуйте субъект не от EcsSubject
, а от EcsSubjectDI
, а далее добавьте специальные атрибуты.
Атрибуты для инициализации полей с пулами:
[Inc]
- кеширует пул и добавит тип компонента в включающее ограничение субъекта, аналог методаInclude
;[Exc]
- кеширует пул и добавит тип компонента в исключающее ограничение субъекта, аналог методаExclude
;[Opt]
- только кеширует пул, аналог методаOptional
;
Атрибут для комбинирования субъектов:
[Combine(order)]
- кеширует субъект и скомбинирует ограничения субъектов, аналог методаCombine
, аргументorder
задает порядок комбинирования, по умлочаниюorder = 0
;
Дополнительные атрибуты только для задания ограничений субъекта. Их можно применить к самому субъекту, либо к любому полю внутри. Используйте атрибуты:
[IncImplicit(type)]
- добавит в включающее ограничение указанный в конструкторе типtype
, аналог методаInclude
;[ExcImplicit(type)]
- добавит в исключающее ограничение указанный в конструкторе типtype
, аналог методаExclude
;
Пример кода
class VelocitySystemDI : IEcsRunProcess
{
class Subject : EcsSubjectDI
{
[ExcImplicit(typeof(FreezedTag))]
[Inc] public EcsPool<Pose> poses;
[Inc] public EcsPool<Velocity> velocities;
}
[EcsInject] EcsDefaultWorld _world;
[EcsInject] TimeService _time;
public void Run(EcsPipeline pipeline)
{
foreach (var e in _world.Where(out Subject s))
{
s.poses.Write(e).position += s.velocities.Read(e).value * _time.DeltaTime;
}
}
}
Тот же код но без AutoInjections
class VelocitySystem : IEcsRunProcess, IEcsInject<EcsDefaultWorld>, IEcsInject<TimeService>
{
class Subject : EcsSubject
{
public EcsPool<Pose> poses;
public EcsPool<Velocity> velocities;
public Subject(Builder b)
{
b.Exclude<FreezedTag>();
poses = b.Include<Pose>();
velocities = b.Include<Velocity>();
}
}
EcsDefaultWorld _world;
TimeService _time;
public void Inject(EcsDefaultWorld obj) => _world = obj;
public void Inject(TimeService obj) => _time = obj;
public void Run(EcsPipeline pipeline)
{
foreach (var e in _world.Where(out Subject s))
{
s.poses.Write(e).position += s.velocities.Read(e).value * _time.DeltaTime;
}
}
}
Не null инъекции
Чтобы поле помеченное [EcsInject]
было проинициализированно даже в случае отстувия инъекции, в конструктор атрибута можно передать тип болванку. В примере ниже поле foo
получит экземпляр класса Foo
из инъекции или экземпляр FooDummy : Foo
если инъекции небыло.
[EcsInject(typeof(FooDummy))] Foo foo;
Переданный тип должен иметь конструктор без параметров и быть либо того же типа что и тип поля, либо производного типа.
Расширение так же сообщит если по завершению предварительной инъекции, остались не проинициализированные поля с [EcsInject]
.