diff --git a/README-RU.md b/README-RU.md new file mode 100644 index 0000000..fae725a --- /dev/null +++ b/README-RU.md @@ -0,0 +1,133 @@ +

+ +

+ +

+Version + GitHub + +

+ +# Auto Injections for [DragonECS](https://github.com/DCFApixels/DragonECS) +Расширение призвано сократить объем кода, упростив инъекцию зависимостей, делая их автоматически. +> **ВАЖНО!** Проект в стадии разработки. API может меняться. +# Оглавление +* [Установка](#Установка) + * [Зависимости](#Зависимости) + * [Unity-модуль](#Unity-модуль) + * [В виде исходников](#В-виде-иходников) +* [Интеграция](#Интеграция) +* [Инъекция зависимостей](#Инъекция-зависимостей) +* [Auto Builder субъектов](#Auto-Builder-субъектов) +* [Пример кода](#Пример-кода) +* [Не null инъекции](#Не-null-инъекции) + +# Установка +### Зависимости +Убедитесь что в проекте установлен фреймворк [DragonECS](https://github.com/DCFApixels/DragonECS). +* ### Unity-модуль +Поддерживается установка в виде Unity-модуля в при помощи добавления git-URL [в PackageManager](https://docs.unity3d.com/2023.2/Documentation/Manual/upm-ui-giturl.html) или ручного добавления в `Packages/manifest.json`: +``` +https://github.com/DCFApixels/DragonECS-AutoInjections.git +``` +* ### В виде исходников +Фреймворк так же может быть добавлен в проект в виде исходников. + +# Интеграция +Добавьте вызов метода `AutoInject()` для Builder-а пайплайна. Пример: +```csharp +_pipeline = EcsPipeline.New() + .Inject(world) + .Inject(_timeService) + .Add(new TestSystem()) + .Add(new VelocitySystem()) + .Add(new ViewSystem()) + .AutoInject() + .BuildAndInit(); +``` + +# Инъекция зависимостей +Атрибут `[EcsInject]` убирает необходимость использования интерфейса `IEcsInject`, поля помеченные таким атрибутом автоматически подхватят зависимости внедренные в Pipeline. Пример: +```csharp +[EcsInject] EcsDefaultWorld _world; +``` +# Auto Builder субъектов +Так же AutoInjections упрощает построение субъектов. Для начала наследуйте субъект не от `EcsSubject`, а от `EcsSubjectDI`, а далее добавьте специальные атрибуты. + +Атрибуты для инициализации полей с пулами: +* `[Inc]` - кеширует пул и добавит тип компонента в включающее ограничение субъекта, аналог метода `Include`; +* `[Exc]` - кеширует пул и добавит тип компонента в исключающее ограничение субъекта, аналог метода `Exclude`; +* `[Opt]` - только кеширует пул, аналог метода `Optional`; + +Дополнительные атрибуты только для задания ограничений субъекта. Их можно применить к самому субъекту, либо к любому полю внутри. Используйте атрибуты: +* `[IncImplicit(type)]` - добавит в включающее ограничение указанный в конструкторе тип `type`, аналог метода `Include`; +* `[ExcImplicit(type)]` - добавит в исключающее ограничение указанный в конструкторе тип `type`, аналог метода `Exclude`; + +# Пример кода +```csharp +class VelocitySystemDI : IEcsRunProcess +{ + class Subject : EcsSubjectDI + { + [ExcImplicit(typeof(FreezedTag))] + [Inc] public EcsPool poses; + [Inc] public EcsPool 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 + +```csharp +class VelocitySystem : IEcsRunProcess, IEcsInject, IEcsInject +{ + class Subject : EcsSubject + { + public EcsPool poses; + public EcsPool velocities; + public Subject(Builder b) + { + b.Exclude(); + poses = b.Include(); + velocities = b.Include(); + } + } + + 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` если инъекции небыло. +``` csharp +[EcsInject(typeof(FooDummy))] Foo foo; +``` +> Для корректной работы переданный тип должен иметь конструктор без парамтров и быть либо того же типа что и поле, либо производного типа. + +Расширение так же сообщит если по завершению предварительной инъекции, остались не проинициализированные поля с `[EcsInject]`.