Editor-time, deterministic injection:BindingsBindingInstruction declared in a Scope that tells Saneject what to resolve, how to inject it, and where to search. are resolved in the editor, stored directly in serialized fields, and everything is wired before runtime.
Familiar, fluent bindingBindingInstruction declared in a Scope that tells Saneject what to resolve, how to inject it, and where to search. API: Saneject's familiar, fluent bindingBindingInstruction declared in a Scope that tells Saneject what to resolve, how to inject it, and where to search. API gives precise control over where dependencies come from and where they may be injected. If you have worked with DI frameworks before, you'll feel right at home.
Component and asset bindingsAsset bindingBinding declared with BindAsset... or BindAssets... that resolves UnityEngine.Object assets from project content instead of scene or hierarchy components.:Component bindingsComponent bindingBinding declared with BindComponent... or BindComponents... that resolves Component instances from transforms, hierarchies, scenes, or explicit instances. and asset bindingsAsset bindingBinding declared with BindAsset... or BindAssets... that resolves UnityEngine.Object assets from project content instead of scene or hierarchy components. are both supported, so dependencies can come from hierarchies, scenes, Resources, and project folders.
Single-value and collection bindingsCollection bindingBinding declared as multiple (BindComponents/BindAssets/BindMultiple...) that resolves arrays or List<> injection sites.: Single-value and collection bindingsCollection bindingBinding declared as multiple (BindComponents/BindAssets/BindMultiple...) that resolves arrays or List<> injection sites. (T[], List<T>) use the same overall model with a consistent API.
Qualifier-based targeting: Qualifiers with ToID, ToTarget, and ToMember let you narrow a bindingBindingInstruction declared in a Scope that tells Saneject what to resolve, how to inject it, and where to search. to specific injection sitesInjection siteInjected field, property or method..
Powerful filtering:.Where(x => ...) predicates let you filter dependencies candidates in hierarchies and assets by custom criteria.
Recursive scopeScopeMonoBehaviour that declares bindings for a part of your hierarchy. fallback: Recursive upwards parent-scope fallback makes it possible to keep local overrides while still sharing common bindingsBindingInstruction declared in a Scope that tells Saneject what to resolve, how to inject it, and where to search. higher in the hierarchy.
Scenes, prefabs & contexts
Context-aware injection: Saneject treats scene objectsScene objectNon-prefab GameObject in a scene., prefab instancesPrefab instanceInstantiated prefab placed in a scene or nested inside another prefab., and prefab assetsPrefab assetReusable prefab definition in the Project window. as separate contextsContextSerialization boundary Saneject uses during injection to decide scope traversal and candidate eligibility. during injection.
Control over what gets processed: You can choose which contextsContextSerialization boundary Saneject uses during injection to decide scope traversal and candidate eligibility. are processed in an injection runInjection runOne execution of the injection pipeline for a chosen selection, context walk filter, and active set of targets., which makes focused validation and iteration easier.
Control over cross-context resolution: You can decide whether dependency resolution is allowed to cross contextContextSerialization boundary Saneject uses during injection to decide scope traversal and candidate eligibility. boundaries or not.
Safer prefab reuse: These contextContextSerialization boundary Saneject uses during injection to decide scope traversal and candidate eligibility. rules help prevent accidental cross-context coupling and make prefab reuse safer across scenes.
Interfaces & serialization
Serializable interface fields and auto-properties: Unity does not serialize interface members by default, so Saneject adds [SerializeInterface] support through Roslyn-generated backing members.
Interfaces in the Inspector: Interface fields remain visible in the Inspector, including arrays and lists of interfaces.
Type-safe Inspector assignment:[SerializeInterface] IGameObservable gameObservable will produce a serialized UnityEngine.Object field in the Inspector that can only be populated with an IGameObservable object.
No wrapper classes needed: Your code stays clean, with no wrapper classes needed just to get interface references into Unity serialization.
Runtime bridging
RuntimeProxy for placeholder injection: For dependencies Unity cannot serialize (scene ↔ other scene; prefab assetPrefab assetReusable prefab definition in the Project window. ↔ other prefab assetPrefab assetReusable prefab definition in the Project window.; scene ↔ prefab assetPrefab assetReusable prefab definition in the Project window.), RuntimeProxy can inject a serialized placeholder asset at editor time and swap it to a real instance during early startup, without reflection.
GlobalScopeGlobal scopeStatic runtime registry and service locator in Saneject for globally accessible Component instances. for fast runtime lookups:GlobalScope is a static runtime registry used for fast type-based lookups, often as a proxy resolve source.
Lazy-loaded runtime bridging: You can think of proxies as a lazy loaded dependency that resolves to a real instance at runtime.
Editor-time wiring stays the default: This keeps your dependency wiring editor-time, while still supporting cross-context runtime cases when you need them.
Low runtime overhead
Fast startup from serialized references: Dependencies are already resolved and serialized before Play Mode starts.
No runtime container initialization: Saneject does not build or bootstrap a runtime DI container.
No reflection-based startup pass: Dependency wiring does not rely on a reflection-driven initialization step.
No second lifecycle on top of Unity's: The runtime is just normal Awake, Start, OnEnable, and the rest of Unity's lifecycle.
Runtime work is limited and optional: Runtime work is mainly limited to features that intentionally, and optionally, run at startup, such as global scopeGlobal scopeStatic runtime registry and service locator in Saneject for globally accessible Component instances. registration and runtime proxyRuntime proxyScriptableObject placeholder asset (RuntimeProxy<TComponent>) injected into interface members at editor time and swapped to the real instance during scope startup. swapping to real instances.
Tooling & validation
Contextual toolbar buttons and injection context menusInjection context menuEditor command under Saneject/Inject Scene/..., Saneject/Inject Selected Scene Hierarchies/..., Saneject/Inject Prefab Asset/..., or the matching GameObject/Saneject/... paths that start an injection run with a selected target and ContextWalkFilter.: The main toolbar exposes Inject Scene, Inject Selected Scene Hierarchies, Inject Prefab Asset, and Batch Inject Selected Assets when they apply, while injection context menusInjection context menuEditor command under Saneject/Inject Scene/..., Saneject/Inject Selected Scene Hierarchies/..., Saneject/Inject Prefab Asset/..., or the matching GameObject/Saneject/... paths that start an injection run with a selected target and ContextWalkFilter. let you run more focused scene, hierarchy, prefab, and selected-asset batch passes with specific context walk filterContext walk filterFilter enum used during graph walk to include specific context sets in a run (AllContexts, SameContextsAsSelection, SceneObjects, PrefabAssetObjects, PrefabInstances). values.
Batch injectionBatch injectionRunning injection across multiple selected scene and prefab assets in one operation.:Batch InjectorBatch InjectorEditor window for preparing and running batch injection with per-asset enable state, status, and ContextWalkFilter. can inject all (or selected) scenes and prefabs in a project in one click.
Structured logging and validation: Structured logging and validation with per-run and batch summaries help make dependency validation repeatable and easier to audit.
Configurable settings: Settings cover injection prompts, logging, contextContextSerialization boundary Saneject uses during injection to decide scope traversal and candidate eligibility. behavior, and proxy generation.
Native Unity UI/UX: Designed to feel at home in Unity with polished inspectors, contextual menus, and intuitive behavior.
Code analysis
Roslyn analyzersRoslyn analyzerCompile-time code analysis component that inspects C# syntax and symbols and reports diagnostics in the IDE and during builds. and code fixes: Saneject ships Roslyn analyzersRoslyn analyzerCompile-time code analysis component that inspects C# syntax and symbols and reports diagnostics in the IDE and during builds. and code fixes for common attribute mistakes, such as invalid [Inject] field serialization setup and incorrect [SerializeInterface] usage.
Issues caught during code analysis: This catches issues during code analysis instead of waiting for injection-time failures.