Editor-time, deterministic injection: Bindings are resolved in the editor, stored directly in serialized fields, and everything is wired before runtime.
Familiar, fluent binding API: Saneject's familiar, fluent binding 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 bindings: Component bindings and asset bindings are both supported, so dependencies can come from hierarchies, scenes, Resources, and project folders.
Single-value and collection bindings: Single-value and collection bindings (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 binding to specific injection sites.
Powerful filtering:.Where(x => ...) predicates let you filter dependencies candidates in hierarchies and assets by custom criteria.
Recursive scope fallback: Recursive upwards parent-scope fallback makes it possible to keep local overrides while still sharing common bindings higher in the hierarchy.
Scenes, prefabs & contexts
Context-aware injection: Saneject treats scene objects, prefab instances, and prefab assets as separate contexts during injection.
Control over what gets processed: You can choose which contexts are processed in an injection run, which makes focused validation and iteration easier.
Control over cross-context resolution: You can decide whether dependency resolution is allowed to cross context boundaries or not.
Safer prefab reuse: These context 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 asset ↔ other prefab asset; scene ↔ prefab asset), RuntimeProxy can inject a serialized placeholder asset at editor time and swap it to a real instance during early startup, without reflection.
GlobalScope 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 scope registration and runtime proxy swapping to real instances.
Tooling & validation
Contextual toolbar buttons and injection context menus: The main toolbar exposes Inject Scene, Inject Hierarchies, Inject Prefab, and Batch Inject when they apply, while injection context menus let you run more focused scene, hierarchy, prefab, and selected-asset batch passes with specific context walk filter values.
Batch injection: Batch Injector 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.
Native Unity UI/UX: Designed to feel at home in Unity with polished inspectors, contextual menus, and intuitive behavior.
Code analysis
Roslyn analyzers and code fixes: Saneject ships Roslyn analyzers 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.