Architecture Overview
High-Level Diagram
flowchart TB
subgraph Consumer
App[Application Code]
end
subgraph SimplEnteiner Core
DIContainer["DIContainer<br/>(IScope, IBindingTarget)"]
Scope["Scope<br/>(IScope, IBindingTarget)"]
Binder["BindingBuilder<br/>+ Fluent Binding API"]
Registry["Registry<br/>(IRegistry)"]
Resolver["Resolver<br/>(IResolver)"]
ConventionBuilder["ConventionBuilder<br/>(IConventionBuilder)"]
CleanupService["CleanupService<br/>(disposal tracking)"]
RepositoryService["RepositoryService<br/>(singleton store)"]
TypeAnalyzes["TypeAnalyzes<br/>(reflection utilities)"]
ReachabilityAnalyzer["ReachabilityAnalyzer"]
end
subgraph MS.DI Integration
Extensions["Extensions.AddSimplEnteiner"]
SEProvider["SimplEnteinerServiceProvider"]
SEScope["SimplEnteinerServiceScope"]
end
App -->|Bind/Decorate/Resolve| DIContainer
DIContainer -->|delegates to root| Scope
Scope -->|creates children| Scope
DIContainer --> Binder
Binder -->|Register| Scope
Scope --> Registry
Scope --> Resolver
Resolver --> Registry
Resolver --> TypeAnalyzes
Scope --> CleanupService
Scope --> RepositoryService
DIContainer --> ConventionBuilder
Registry --> ReachabilityAnalyzer
App -->|AddSimplEnteiner| Extensions
Extensions --> DIContainer
Extensions --> SEProvider
SEProvider --> Scope
SEProvider --> SEScope
Layers
SimplEnteiner is organized into the following logical layers, all living under SimplEnteiner/Core:
- Binder layer (
Core/Binder) — the public fluent API surface (Bind<T>(),Decorate<T>()) and the internal staged state machine (BindingBuilder,BuilderStages) that guarantees bindings are configured in a valid order and only registered once. - Registration layer (
Core/RegistrationService) — theRegistrythat stores exact, open-generic, conditional, and decorator registrations, plus the validation logic that ensures a registration's dependencies are resolvable and its constraints are satisfied. - Resolution layer (
Core/ResolverService) — theResolver, which walks the constructor/member dependency graph, creates instances via compiled factory delegates, applies lifetime-specific caching/storage, and wraps instances with decorators. - Scope layer (
Core/ScopeFeature) —Scope/IScope, the hierarchical container implementation that owns aRegistry, a singleton repository, scoped instance dictionary, child scopes, and drives disposal. - Lifecycle layer (
Core/Lifecycle) — lifetime enum, initialization/startup interfaces (IInitializable,IAsyncInitializable,IStartable), and theCleanupServicethat tracksIDisposable/IAsyncDisposableinstances for correct teardown. - Convention layer (
Core/ConventionBinding) — assembly-scanning, predicate/attribute/namespace-filtered auto-registration (ConventionBuilder). - Configuration/Serialization layer (
Core/Configuration) — DTOs (ScopeConfig,BindingConfig,DecoratorConfig) used to serialize/deserialize a container's registration graph to/from JSON. - Reflection toolkit (
SimplEnteiner.TypeAnalyzes, top-level namespaceSimplEnteiner) — a large, independently reusable set ofType/ConstructorInfo/MemberInfoextension methods with a lazily-initialized, thread-safe, process-wide cache of loadable types. - Analysis layer (
SimplEnteiner.Analysis) —ReachabilityAnalyzer, used to compute the set of types reachable from a set of "root" service types, used both byRegistry.AnalyzeReachabilityand directly by consumers. - Integration layer (
SimplEnteiner.Integrations.MS_DI) — adapters (SimplEnteinerServiceProvider,SimplEnteinerServiceScope,Extensions.AddSimplEnteiner) that expose aDIContainer/IScopeas a standardIServiceProvider/IServiceScopeFactory.
Root Container vs. Scope
DIContainer (public entry point, Core/DIContainer.cs) is a thin façade over an internal root Scope. It implements both IScope (so it can be used anywhere an IScope is expected) and the internal IBindingTarget interface (used to receive registrations produced by the fluent binder). All actual bookkeeping — registry, singleton store, children, cleanup — lives in the Scope it wraps.
classDiagram
class IScope {
<<interface>>
+IScope Parent
+IRegistry Registry
+bool IsRoot
+Resolve~T~() T
+ResolveAsync~T~() Task~T~
+CreateScope() IScope
+Build()
}
class IBinder {
<<interface>>
+Bind~T~() IBindingTo~T~
+Decorate~T~() IBindingDecorate~T~
+BindConvention(Action)
}
class DIContainer {
-Scope _rootScope
-List~BindingBuilder~ _pendingBindings
-IResolver _resolver
+ExportConfiguration() string
+ImportConfiguration(string)
+AnalyzeReachability(roots, injectAttr)
}
class Scope {
-IRegistry _registry
-IRepositoryService _singletons
-Dictionary~Type,object~ _scopedInstances
-List~IScope~ _childrens
-ICleanupService _cleanupService
+Install(IInstaller)
+Build()
}
IScope <|-- IBinder
IScope <|.. DIContainer
IScope <|.. Scope
DIContainer o-- Scope : wraps root
Scope o-- Scope : children
Continue to Design Patterns for the rationale behind this structure, or to Namespace Structure for a file/namespace map.