{"id":13676446,"url":"https://github.com/gustavopsantos/reflex","last_synced_at":"2026-02-24T04:06:26.518Z","repository":{"id":43464135,"uuid":"393806936","full_name":"gustavopsantos/Reflex","owner":"gustavopsantos","description":"Minimal dependency injection framework for Unity","archived":false,"fork":false,"pushed_at":"2025-04-13T19:36:11.000Z","size":36231,"stargazers_count":831,"open_issues_count":1,"forks_count":60,"subscribers_count":12,"default_branch":"main","last_synced_at":"2025-04-25T10:43:06.169Z","etag":null,"topics":["container","csharp","dependency-injection","di","game-dev","injection","ioc","ioc-container","package","unity","unity3d"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gustavopsantos.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2021-08-07T22:37:26.000Z","updated_at":"2025-04-25T10:04:32.000Z","dependencies_parsed_at":"2023-02-17T21:45:42.725Z","dependency_job_id":"6ed0e0f8-2062-4932-9372-fbe627411b05","html_url":"https://github.com/gustavopsantos/Reflex","commit_stats":null,"previous_names":[],"tags_count":66,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gustavopsantos%2FReflex","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gustavopsantos%2FReflex/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gustavopsantos%2FReflex/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gustavopsantos%2FReflex/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gustavopsantos","download_url":"https://codeload.github.com/gustavopsantos/Reflex/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251455907,"owners_count":21592260,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["container","csharp","dependency-injection","di","game-dev","injection","ioc","ioc-container","package","unity","unity3d"],"created_at":"2024-08-02T13:00:27.197Z","updated_at":"2026-01-15T03:39:02.310Z","avatar_url":"https://github.com/gustavopsantos.png","language":"C#","readme":"\u003cdiv align=center\u003e   \n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"Graphics\\logo.png\" width=\"250\"\u003e\n\u003c/p\u003e\n\n### Blazing fast, minimal but complete dependency injection library for \u003ca href=\"https://unity.com/\"\u003eUnity\u003c/a\u003e\n\nReflex is an [Dependency Injection](https://stackify.com/dependency-injection/) framework for [Unity](https://unity.com/). Making your classes independent of its dependencies, granting better separation of concerns. It achieves that by decoupling the usage of an object from its creation. This helps you to follow SOLID’s dependency inversion and single responsibility principles. Making your project more **readable, testable and scalable.**\n\n[![Discord](https://img.shields.io/static/v1?label=\u0026labelColor=5865F2\u0026message=Support\u0026color=grey\u0026logo=Discord\u0026logoColor=white\u0026url=https://discord.gg/XM47TsGScH)](https://discord.gg/XM47TsGScH)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n![](https://github.com/gustavopsantos/reflex/workflows/Tests/badge.svg)\n[![PullRequests](https://img.shields.io/badge/PRs-welcome-blueviolet)](http://makeapullrequest.com)\n[![Releases](https://img.shields.io/github/release/gustavopsantos/reflex.svg)](https://github.com/gustavopsantos/reflex/releases)\n[![OpenUPM](https://img.shields.io/npm/v/com.gustavopsantos.reflex?label=OpenUPM\u0026registry_uri=https://package.openupm.com)](https://openupm.com/packages/com.gustavopsantos.reflex/)\n[![Unity](https://img.shields.io/badge/Unity-2021+-black.svg)](https://unity3d.com/pt/get-unity/download/archive)\n\n\u003c/div\u003e\n\n---\n\n\u003cdetails\u003e\n\u003csummary\u003e📌 Table Of Contents\u003c/summary\u003e\n\n- [Overview](#-overview)\n- [Installation](#-installation)\n  - [Unity Package Manager](#unity-package-manager)\n  - [Open Unity Package Manager](#open-unity-package-manager)\n  - [Unity Package](#unity-package)\n- [Getting Started](#-getting-started)\n- [Execution Order](#-execution-order)\n- [Injection Strategy](#-injection-strategy)\n- [Container Hierarrchy](#-container-hierarchy)\n- [Scopes](#-scopes)\n- [Bindings](#-bindings)\n- [Resolving](#-resolving)\n- [Callbacks](#-callbacks)\n- [Attributes](#-attributes)\n- [Manual Injection](#-manual-injection)\n- [Extensions](#-extensions)\n- [Debugger](#-debugger)\n- [Settings](#-settings)\n- [Performance](#-performance)\n- [Scripting Restrictions](#-scripting-restrictions)\n- [Support](#-support)\n- [License](#-license)\n\n\u003c/details\u003e\n\n---\n\n## 👀 Overview\n- **Fast:** up to 414% faster than VContainer, up to 800% faster than Zenject.\n- **GC Friendly:** up to 28% less allocations than VContainer, up to 921% less allocations than Zenject.\n- **AOT Support:** Basically there's no runtime Emit, so it works fine on IL2CPP builds. [\u003csup\u003e[*]\u003c/sup\u003e](#-scripting-restrictions)\n- **Contract Table:** Allows usages of APIs like `container.All\u003cIDisposable\u003e`\n- **Immutable Container**: Performant thread safety free of lock plus predictable behavior.\n\nCompatible with the following platforms:\n\n- iOS\n- Android\n- Windows/Mac/Linux\n- PS4/PS5\n- Xbox One/S/X and Xbox Series X/S\n- WebGL\n\n---\n\n## 💾 Installation\nYou can install Reflex using any of the following methods:\n\n### Unity Package Manager\n```\nhttps://github.com/gustavopsantos/reflex.git?path=/Assets/Reflex/#10.0.2\n```\n\n1. In Unity, open **Window** → **Package Manager**.\n2. Press the **+** button, choose \"**Add package from git URL...**\"\n3. Enter url above and press **Add**.\n\n### Open Unity Package Manager\n\n```bash\nopenupm install com.gustavopsantos.reflex\n```\n\n### Unity Package\n1. Download the .unitypackage from [releases](https://github.com/gustavopsantos/reflex/releases) page.\n2. Import Reflex.X.X.X.unitypackage\n\n---\n\n## 🚀 Getting Started\n1. [Install Reflex](#-installation)\n2. Create `ProjectInstaller.cs` with \n```csharp\nusing Reflex.Core;\nusing UnityEngine;\n\npublic class ProjectInstaller : MonoBehaviour, IInstaller\n{\n    public void InstallBindings(ContainerBuilder builder)\n    {\n        builder.AddSingleton(\"Hello\");\n    }\n}\n```\n3. In unity project window\n4. Right click over any folder, Create → Reflex → ProjectScope. Since ProjectScopes is strongly referenced by ReflexSettings, you can create it anywhere, it does not need to be inside `Resources` folder.\n5. Select `ProjectScope` you just created\n6. Add `ProjectInstaller.cs` as a component\n7. Create directory `Assets/Resources`\n8. Right click over `Resources` folder, Create → Reflex → Settings. ReflexSettings should always be created inside `Resources` folder.\n9. Select `ReflexSettings` ScriptableObject and add the `ProjectScope` prefab to the ProjectScopes list\n10. Create new scene `Greet`\n11. Add `Greet` to `Build Settings` → `Scenes In Build`\n12. Create `Greeter.cs` with\n```csharp\nusing UnityEngine;\nusing System.Collections.Generic;\nusing Reflex.Attributes;\n\npublic class Greeter : MonoBehaviour\n{\n    [Inject] private readonly IEnumerable\u003cstring\u003e _strings;\n\n    private void Start()\n    {\n        Debug.Log(string.Join(\" \", _strings));\n    }\n}\n```\n13. Add `Greeter.cs` to any gameobject in `Greet` scene\n14. Inside Greet scene, create a new empty gameobject named `SceneScope` and attach `SceneScope` component\n15. Create `GreetInstaller.cs` with\n```csharp\nusing Reflex.Core;\nusing UnityEngine;\n\npublic class GreetInstaller : MonoBehaviour, IInstaller\n{\n    public void InstallBindings(ContainerBuilder builder)\n    {\n        builder.AddSingleton(\"World\");\n    }\n}\n```\n16. Add `GreetInstaller.cs` to `Greet.unity` `SceneScope`\n17. Create new scene `Boot`\n18. Add `Boot` to `Build Settings` → `Scenes In Build`\n19. Create `Loader.cs` with\n```csharp\nusing Reflex.Core;\nusing UnityEngine;\nusing UnityEngine.SceneManagement;\n\npublic class Loader : MonoBehaviour\n{\n    private void Start()\n    {\n\t// If you are loading scenes without addressables\n\tvar scene = SceneManager.LoadScene(\"Greet\", new LoadSceneParameters(LoadSceneMode.Single));\n\tReflexSceneManager.PreInstallScene(scene, builder =\u003e builder.AddSingleton(\"Beautiful\"));\n\n\t// If you are loading scenes with addressables\n\tAddressables.LoadSceneAsync(\"Greet\", activateOnLoad: false).Completed += handle =\u003e\n\t{\n\t\tReflexSceneManager.PreInstallScene(handle.Result.Scene, builder =\u003e builder.AddSingleton(\"Beautiful\"));\n\t\thandle.Result.ActivateAsync();\n\t};\n    }\n}\n```\n20. Assign it to any gameobject at `Boot` scene\n21. Thats it, hit play while on `Boot` scene\n22. When Greet scene is loaded, there should be 3 instances implementing string contract\n23. So when Greeter::Start is called, you should see the following log in the unity console: `Hello Beautiful world`\n\n---\n\n## 🎬 Execution Order\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"Graphics/execution-order.png\" /\u003e\n\u003c/p\u003e\n\n---\n\n## 🎯 Injection Strategy\nAs of version 8.0.0 Reflex has stopped automatically managing dependency injection for any scene.\n\nIf you plan on using dependency injection in one of your scenes, add a game object somewhere in the hierarchy with a `SceneScope` component attached. You can still manage dependencies project-wide or utilize this scene container for limited access. This component must be present at scene load time.\n\nThis allows users to consume injected dependencies on callbacks such as `Awake` and `OnEnable` while giving more granular control over which scene should be injected or not.\n\n---\n\n## 🌱 Container Hierarchy\n### Default Behaviour\nReflex's default strategy for creating containers involves initially generating a root project container. For each newly loaded scene, an additional container is created, which always inherits from the root project container. This container hierarchy mirrors the flat hierarchy of Unity scenes. You can see how the structure looks like below:\n\n```mermaid\ngraph\nProjectContainer --\u003e BootScene\nProjectContainer --\u003e LobbyScene\nProjectContainer --\u003e GameModeOneScene\nProjectContainer --\u003e GameModeTwoScene\n```\n\n### Scene Parent Override\n\nIf you want a scene to inherit services from another scene, you can use the `ReflexSceneManager::OverrideSceneParentContainer` method. This feature provides developers with more granular control over which parent container is used for each newly loaded scene.\n\n```csharp\n// Scene Manager Sample\nvar bootScene = SceneManager.GetSceneByName(\"Boot\");  \nvar sessionScene = SceneManager.LoadScene(\"Session\", new LoadSceneParameters(LoadSceneMode.Additive));  \nReflexSceneManager.OverrideSceneParentContainer(scene: sessionScene, parent: bootScene.GetSceneContainer());\n\n// Addessable Sample\nvar handle = Addressables.LoadSceneAsync(\"Session\", LoadSceneMode.Additive, activateOnLoad: false);\nawait handle.Task;\nvar bootScene = SceneManager.GetSceneByName(\"Boot\");\nReflexSceneManager.OverrideSceneParentContainer(scene: handle.Result.Scene, parent: bootScene.GetSceneContainer());\nhandle.Result.ActivateAsync();\n```  \n\nBy utilizing this API, you can create hierarchical structures such as the one shown below:\n\n```mermaid\ngraph\nProjectContainer--\u003eBootScene\nBootScene--\u003eLobbyScene\nLobbyScene--\u003eGameModeOneScene\nLobbyScene--\u003eGameModeTwoScene\n```\n\n\n\u003e1. Please note that it is not possible to override the parent container for the initial scene loaded by Unity.\n\u003e2. Exercise caution when managing the scene lifecycle with this type of hierarchy. For example, unloading a parent scene before its child scenes can lead to unexpected behavior, as the parent container will be disposed while the child scenes are still active. As a general rule, always unload the scene hierarchy from the bottom up, starting with the child scenes and progressing to the parent scenes.\n\n\n\n---\n\n## 📦 Scopes\nContainer scoping refers to the ability of being able to create a container inheriting the registrations of its parent container while also being able to extend it.\n\n### Project Scope\nIt is root scope.\nIt is created just before first scene opens by relying on `[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]`\nTo register bindings to it, create a prefab, name it how you wish, the name is not used as a identifier, and attach a \"ProjectScope\" component to it.\nSelect ReflexSettings and add your ProjectScope prefab to the list of ProjectScopes.\nThen, create your installer as MonoBehaviour and implement IInstaller interface.\nRemember to attach your installer to the ProjectScope prefab, as ProjectScope searches for every child implementing IInstaller when it's time to create the ProjectScope container.\nThere's a menu item to ease the process: Assets \u003e Create \u003e Reflex \u003e ProjectScope\nYou can create multiple ProjectScope prefabs, and when its time to create the project container, all active ProjectScope prefabs will be merged, this allow a better separation of concerns if required.\nNote that ProjectScope prefab is not required, in case Reflex does not find any ProjectScope, an empty root will be created.\nProjectScope instance will be disposed once app closes/app quits.\n\u003e Note that unity does not call OnDestroy deterministically, so rule of thumb is do not rely on injected dependencies on OnDestroy event functions.\n\n### Scene Scope\nIt is scoped from ProjectScope, inheriting all bindings from ProjectScope.\nIt is created and injected before Awake. \nTo register bindings to it, create a gameobject on desired scene, name it \"SceneScope\", put it as root game object, and attach a \"SceneScope\" component to it.\nThen, create your installer as MonoBehaviour and implement IInstaller interface.\nRemember to attach your installer to your SceneScope gameobject, as SceneScope searches for every child implementing IInstaller when it's time to create the SceneScope container.\nThere's a menu item to ease the process: GameObject \u003e Reflex \u003e Scene Context\nRemember to have a single SceneScope to avoid undesired behaviour.\nNote that SceneScope gameobject is required only if you want its scene to be injected, in case Reflex do not find SceneScope, the scene injection will be skipped for that specific scene missing SceneScope.\nSceneScope instance will be disposed once scene is unloaded.\n\u003e Note that unity does not call OnDestroy deterministically, so rule of thumb is do not rely on injected dependencies on OnDestroy event functions. \n\n### Manual Scoping\n```csharp\nusing var scopedContainer = parentContainer.Scope(builder =\u003e  \n{  \n  // Extend your scoped container by adding extra registrations here  \n});\n```\n\n## 🔩 Bindings\n\n### AddSingleton (From Type)\n```csharp\nContainerBuilder::AddSingleton(Type concrete, params Type[] contracts)\n```\nAdds a deferred object creation based on the type to be constructed and its contracts.\nThe object will be constructed lazily, once first request to resolve any of its contracts is called.\nThen **same** object will always be returned.\nIf object implements `IDisposable` it will be disposed when its parent Container are disposed.\nThere's no need to pass `IDisposable` as contract to have your object disposed, however, if you want to retrieve all `IDisposable` by any API `Single\u003cTContract\u003e`, `Resolve\u003cTContract\u003e` or `All\u003cTContract\u003e` then yes, you have to specify it.\n\n### AddSingleton (From Value)\n```csharp\nContainerBuilder::AddSingleton(object instance, params Type[] contracts)\n```\nAdds an object already constructed by the user to the container as a singleton, everytime the contracts given is asked to be resolved, the same object will be returned.\nIf object implements `IDisposable` it will be disposed when its parent Container are disposed.\nThere's no need to pass `IDisposable` as contract to have your object disposed, however, if you want to retrieve all `IDisposable` by any API `Single\u003cTContract\u003e`, `Resolve\u003cTContract\u003e` or `All\u003cTContract\u003e` then yes, you have to specify it.\n\n### AddSingleton (From Factory)\n```csharp\nContainerBuilder::AddSingleton\u003cT\u003e(Func\u003cContainer, T\u003e factory, params Type[] contracts)\n```\nAdds a deferred object creation based on the given factory and its contracts.\nThe object will be constructed lazily, once first request to resolve any of its contracts is called.\nThe factory will be ran once, and then the **same** object will always be returned.\nIf object implements `IDisposable` it will be disposed when its parent Container are disposed.\nThere's no need to pass `IDisposable` as contract to have your object disposed, however, if you want to retrieve all `IDisposable` by any API `Single\u003cTContract\u003e`, `Resolve\u003cTContract\u003e` or `All\u003cTContract\u003e` then yes, you have to specify it.\n\n### AddTransient (From Type)\n```csharp\nContainerBuilder::AddTransient(Type concrete, params Type[] contracts)\n```\nAdds a deferred object creation based on the type to be constructed and its contracts.\nThe object will be constructed lazily, once first request to resolve any of its contracts is called.\nThen for any request of any contract, a new object will be created, use this carefully.\nIf object implements `IDisposable` it will be disposed when the container who constructed the instance are disposed, and eventually collected when GC kicks in.\nThere's no need to pass `IDisposable` as contract to have your object disposed, however, if you want to retrieve all `IDisposable` by any API `Single\u003cTContract\u003e`, `Resolve\u003cTContract\u003e` or `All\u003cTContract\u003e` then yes, you have to specify it.\n\n### AddTransient (From Factory)\n```csharp\nContainerBuilder::AddTransient(Func\u003cContainer, T\u003e factory, params Type[] contracts)\n```\nAdds a deferred object creation based on the given factory and its contracts.\nThe object will be constructed lazily, once first request to resolve any of its contracts is called.\nThen for any request of any contract, a new object will be created, use this carefully.\nIf object implements `IDisposable` it will be disposed when the container who constructed the instance are disposed, and eventually collected when GC kicks in.\nThere's no need to pass `IDisposable` as contract to have your object disposed, however, if you want to retrieve all `IDisposable` by any API `Single\u003cTContract\u003e`, `Resolve\u003cTContract\u003e` or `All\u003cTContract\u003e` then yes, you have to specify it.\n\n### AddScoped (From Type)\n```csharp\nContainerBuilder::AddScoped(Type concrete, params Type[] contracts)\n```\nVery similar to AddSingleton API, however, instead of having a single global instance, AddScoped creates one object instance per container.\nIf object implements `IDisposable` it will be disposed when the container who constructed the instance are disposed, and eventually collected when GC kicks in.\nThere's no need to pass `IDisposable` as contract to have your object disposed, however, if you want to retrieve all `IDisposable` by any API `Single\u003cTContract\u003e`, `Resolve\u003cTContract\u003e` or `All\u003cTContract\u003e` then yes, you have to specify it.\n\n### AddScoped (From Factory)\n```csharp\nContainerBuilder::AddScoped(Func\u003cContainer, T\u003e factory, params Type[] contracts)\n```\nVery similar to AddSingleton API, however, instead of having a single global instance, AddScoped creates one object instance per container.\nIf object implements `IDisposable` it will be disposed when the container who constructed the instance are disposed, and eventually collected when GC kicks in.\nThere's no need to pass `IDisposable` as contract to have your object disposed, however, if you want to retrieve all `IDisposable` by any API `Single\u003cTContract\u003e`, `Resolve\u003cTContract\u003e` or `All\u003cTContract\u003e` then yes, you have to specify it.\n\n## 🔍 Resolving\n### Constructor\nIf your type is non-mono, and it's going to be created by the container, then the most recommended way to inject dependencies into it its by constructor injection.\nIt's simply as just requesting the contracts you need as following example:\n```csharp\nprivate class Foo\n{  \n\t...\n  \n\tpublic Foo(IInputManager inputManager, IEnumerable\u003cIManager\u003e managers)  \n\t{  \n\t\t...\n\t}  \n}\n```\n\n\u003e Note that constructor injection relies on `Resolve\u003cTContract\u003e` API, so in case there's two objects with `IInputManager` contract, the last one will be injected. \n\n### Attribute\nAttribute injection is the way to go for **MonoBehaviours**.\nYou can use it to inject fields, writeable properties and methods like following:\n```csharp\nclass Foo : MonoBehaviour  \n{  \n\t[Inject] private readonly IInputManager _inputManager;  \n\t[Inject] public IEnumerable\u003cIManager\u003e Managers { get; private set; }  \n  \n\t[Inject]  \n\tprivate void Inject(IEnumerable\u003cint\u003e numbers) // Method name here does not matter  \n\t{  \n\t  ...\n\t}  \n}\n```\n\u003e Note that attribute injection also works on non-mono classes.\n### Single\n`Container::Single\u003cTContract\u003e` actually validates that there's a single binding implementing given contract, and returns it.\nIf there's more than one the following exception will be thrown.\n```\nInvalidOperationException: Sequence contains more than one element\n```\nIt's recommended for every binding that you know that there should be a single binding implementing the contract.\n### Resolve\n`Container::Resolve\u003cTContract\u003e` runs no validations, and return the last valid object implementing given contract.\n\n### All\n`Container::All\u003cTContract\u003e` returns all objects implementing given contract.\nExample:\n```csharp\nprivate void Documentation_Bindings()  \n{\n\tvar container = new ContainerBuilder()\n\t\t.AddSingleton(1)\n\t\t.AddSingleton(2)\n\t\t.AddSingleton(3)\n\t\t.Build();\n\n\tDebug.Log(string.Join(\", \", container.All\u003cint\u003e())); // Prints: 1, 2, 3\n}\n```\n\n---\n\n## 🪝 Callbacks\n### `ContainerBuilder::OnContainerBuilt`\nOnContainerBuilt is a instance callback of ContainerBuilder, it is called once the container is fully built and initialized properly. \n\n---\n\n## 🔖 Attributes\n### InjectAttribute\nShould be used to inject fields, writeable properties and methods like following:\n```csharp\nclass Foo : MonoBehaviour  \n{  \n\t[Inject] private readonly IInputManager _inputManager;  \n\t[Inject] public IEnumerable\u003cIManager\u003e Managers { get; private set; }  \n  \n\t[Inject]  \n\tprivate void Inject(IEnumerable\u003cint\u003e numbers) // Method name here does not matter  \n\t{  \n\t  ...\n\t}  \n}\n```\n\u003e Note that `InjectAttribute` also works on non-mono classes.\n\n### ReflexConstructorAttribute\nCan be placed on constructors, telling reflex which constructor to use when instantiating an object.\nBy default its not required, as usually injected classes have a single constructor, so by default reflex tries to find the constructor with most arguments.\nBut sometimes this can be required if you need more granular control on which construtor reflex should use.\n\n---\n\n## 💉 Manual Injection\n\nIf objects (plain old c# objects or unity objects) are created during runtime, theres no way reflex can detect this creation to auto inject the object, this needs to be done manually using one of the following methods:\n\n```csharp\nAttributeInjector::void Inject(object obj, Container container)\n// Injects given object fields, properties and methods that was annotated with Inject attribute\n```\n\n```csharp\nConstructorInjector::object Construct(Type concrete, Container container)\n// construct object of given type, using the constructor with most parameters, using given container to pull the constructor arguments\n```\n\n```csharp\nGameObjectInjector::void InjectSingle(GameObject gameObject, Container container)\n// Optimized code meant to find injectables (MonoBehaviours) from a given GameObject, to then, inject using AttributeInjector\n// This option injects only the first MonoBehaviour found on the given GameObject\n```\n\n```csharp\nGameObjectInjector::void InjectObject(GameObject gameObject, Container container)\n// Optimized code meant to find injectables (MonoBehaviours) from a given GameObject, to then, inject using AttributeInjector\n// This option injects all MonoBehaviours found on the given GameObject (not recursively, so it does not account for children) \n```\n\n```csharp\nGameObjectInjector::void InjectRecursive(GameObject gameObject, Container container)\n// Optimized code meant to find injectables (MonoBehaviours) from a given GameObject, to then, inject using AttributeInjector\n// This option injects all MonoBehaviours found on the given GameObject and its childrens recursively \n```\n\n```csharp\nGameObjectInjector::void InjectRecursiveMany(List\u003cGameObject\u003e gameObject, Container container)\n// Optimized code meant to find injectables (MonoBehaviours) from a given GameObject, to then, inject using AttributeInjector\n// This option injects all MonoBehaviours found on the given list of GameObject and its childrens recursively \n```\n### Components\nAn alternative approach is to utilize the `GameObjectSelfInjector`, which can be attached to a prefab to resolve its dependencies at runtime. Through the inspector, you can select the injection strategy: `Single`, `Object`, or `Recursive`. Each strategy invokes the corresponding method in the `GameObjectInjector` class.\n\n---\n\n## 🧩 Extensions\n```csharp\n// Allows you to get a scene container, allowing you to resolve/inject dependencies in a different way during runtime\nSceneExtensions::GetSceneContainer(this Scene scene)\n{\n    return UnityInjector.ContainersPerScene[scene];\n}\n\n// Usage example:\nvar foo = gameObject.scene.GetSceneContainer().Resolve\u003cIFoo\u003e();\n```\n\n---\n\n## 🐛 Debugger\n\nIt can be accessed from menu item  Window → Analysis → Reflex Debugger, or from shortcut CTRL + E.  \nTo enable reflex debug mode you must go to Edit → Project Settings → Player, then in the Other Settings panel, scroll down to Script Compilation → Scripting Define Symbols and add `REFLEX_DEBUG`. This can be easily achieved by clicking on the bug button at bottom right corner inside Reflex Debugger Window.\n\u003e Note that debug mode reduces performance and increases memory pressure, so use it wisely.  \n\n![Preview](Graphics/reflex-debugger.png)  \n\n### Legend\n\n| Icon                                                                                                    | Name                                                                                                                                                                                            | Description                                                                                                                                                                          |\n|---------------------------------------------------------------------------------------------------------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| \u003cimg style='vertical-align:middle;' src='Graphics\\icon-container.png' alt=\"Container Icon\" width=\"24\"\u003e  | Name taken from `Name` property of a `Container` instance. Scene containers uses `scene.name` + `scene.GetHashCode()`, so you can differentiate between two instances of the same opened scene. | Represents a container, containers has a collection of bindings                                                                                                                      |\n| \u003cimg style='vertical-align:middle;' src='Graphics\\icon-resolver.png' alt=\"Container Icon\" width=\"24\"\u003e   | Name created from the array of contracts you described your binding.                                                                                                                            | Represents a binding, bindings has a collection of instances, singleton will have only one instance, transients can have many instances and factories depends on your implementation |\n| \u003cimg style='vertical-align:middle;' src='Graphics\\icon-instance.png' alt=\"Container Icon\" width=\"24\"\u003e   | Name taken from `Name` property of the `Type` of the concrete object.                                                                                                                           | Represents a instance, it's the concrete object that were created by the parent binding and it's being injected to consumers                                                           |\n\nDebugger window allows you to inspect the following:\n- Hierarchy of Containers, Bindings and Instances\n- Binding Contracts, Kind and Lifetime\n- Binding Resolution Count\n- Container construction call stack (who created the container)\n- Binding construction call stack (who created the binding)\n- Instance construction call stack (who resolved the binding making selected instance to be instantiated)\n\n---\n\n## 🪛 Settings\nIt's a  `ReflexSettings` scriptable object instance, named `ReflexSettings` that should live inside a `Resources` folder.\nIt can be created by asset menu item Assets → Create → Reflex → Settings.\n\n- logging verbosity is configured in this asset, and default value is set to `Info`\n- the list of ProjectScopes is also configured in this asset, and default value is empty\n\n\u003e ReflexSettings asset is obligatory to have\n\n---\n\n## 📊 Performance\n\u003e Resolving ten thousand times a transient dependency with four levels of chained dependencies. See [NestedBenchmarkReflex.cs](Assets/Reflex.Benchmark/NestedBenchmarkReflex.cs).\n\n### Android + Mono\n|            |       GC |     Time | GC Ratio | Time Ratio |\n|------------|---------:|---------:|---------:|-----------:|\n| Reflex     |  54.7 KB |    4.9ms |     100% |       100% |\n| Zenject    | 503.9 KB |   34.4ms |     921% |       702% |\n| VContainer |  70.3 KB |   20.3ms |     128% |       414% |\n\n### Android + IL2CPP\n|           |        GC |   Time | GC Ratio | Time Ratio |\n|-----------|----------:|-------:|---------:|-----------:|\n| Reflex    |  140.6 KB |  4.0ms |     100% |       100% |\n| Zenject   |   1000 KB | 15.8ms |     711% |       395% |\n| VContainer|  140.6 KB |  4.2ms |     100% |       105% |\n\n### Windows + Mono\n|           |         GC |   Time | GC Ratio | Time Ratio |\n|-----------|-----------:|-------:|---------:|-----------:|\n| Reflex    |   140.6 KB |  0.7ms |     100% |       100% |\n| Zenject   |    1000 KB |  5.6ms |     711% |       800% |\n| VContainer|   140.6 KB |  1.9ms |     100% |       271% |\n\n### Windows + IL2CPP\n|           |       GC |   Time | GC Ratio | Time Ratio |\n|-----------|---------:|-------:|---------:|-----------:|\n| Reflex    | 140.6 KB |  1.4ms |     100% |       100% |\n| Zenject   |  1000 KB |  6.2ms |     711% |       442% |\n| VContainer| 140.6 KB |  3.0ms |     100% |       214% |\n\n## 🚫 Scripting Restrictions\nIf you are taking advantage of reflex to inject `IEnumerable\u003cT\u003e` in your constructors **AND** your are building for **IL2CPP**, you will probably get some exceptions like following:\n\n```\nSystem.ExecutionEngineException: Attempting to call method 'System.Linq.Enumerable::Cast\u003cANY-TYPE\u003e' for which no ahead of time (AOT) code was generated.\n```\n\nThis happens because compiler does not know at compile time that a specific `System.Linq.Enumerable::Cast\u003cT\u003e` should be included. And currently Reflex does not implement any type of assembly weaving.\n\u003e Reflex 4.0.0 had and assembly weaver that was relying on unity UnityEditor.Compilation.CompilationPipeline events and Mono.Cecil. But it was causing conflicts with projects using Burst. So it's being removed temporarly until a definitive solution is found.\n\u003e Most probably we are going to weave assemblies the same way unity is doing for Burst as well.\n\nTemporary workaround example:\n\n```csharp\nclass NumberManager\n{\n    public IEnumerable\u003cint\u003e Numbers { get; }\n\n    public NumberManager(IEnumerable\u003cint\u003e numbers)\n    {\n        Numbers = numbers;\n    }\n    \n    // https://docs.unity3d.com/Manual/ScriptingRestrictions.html\n    [Preserve] private static void UsedOnlyForAOTCodeGeneration()\n    {\n        Array.Empty\u003cobject\u003e().Cast\u003cint\u003e(); // This compiler hint will get rid of: System.ExecutionEngineException: Attempting to call method 'System.Linq.Enumerable::Cast\u003cSystem.Int32\u003e' for which no ahead of time (AOT) code was generated. \n        throw new Exception(\"This method is used for AOT code generation only. Do not call it at runtime.\");\n    }\n}\n```\n\n## 🤝 Support\n\nAsk your questions and participate in discussions regarding Reflex related and dependency injection topics at the Reflex Discord server. \n\n\u003ca href=\"https://discord.gg/XM47TsGScH\"\u003e\u003cimg src=\"https://amplication.com/images/discord_banner_purple.svg\" /\u003e\u003c/a\u003e\n\n---\n\n## 📜 License\nReflex is distributed under the terms of the MIT License.\nA complete version of the license is available in the [LICENSE](LICENSE) file in\nthis repository. Any contribution made to this project will be licensed under\nthe MIT License.\n","funding_links":[],"categories":["Open Source Repositories"],"sub_categories":["Dependency Injection"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgustavopsantos%2Freflex","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgustavopsantos%2Freflex","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgustavopsantos%2Freflex/lists"}