### Resolution Tree Example Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/getting-started/glossary.md Illustrates the instantiation order of dependencies required to resolve a target type. This helps visualize the dependency graph. ```cs class A { public A(B b, C c) { } } class B { public B(C c, D d) { } } class C { } class D { } ``` -------------------------------- ### ConstructorNotFoundException Example Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/diagnostics/validation.md Shows how ConstructorNotFoundException is thrown when attempting to register a service with non-existent constructor argument types. ```csharp class Service { public Service(Dependency dep) { } } container.Register(options => options.WithConstructorByArgumentTypes(typeof(string), typeof(int))); ``` ```text Constructor not found for Namespace.Service with the given argument types: System.String, System.Int32. ``` -------------------------------- ### Property/Field Injection Example Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/guides/service-resolution.md Shows how to register and resolve a service with property/field injection enabled. Use 'WithAutoMemberInjection()' during registration to allow Stashbox to inject properties. ```cs class DbBackup : IJob { public ILogger Logger { get; set; } public IEventBroadcaster EventBroadcaster { get; set; } public DbBackup() { } } container.Register(); container.Register(); // registration of service with auto member injection. container.Register(options => options.WithAutoMemberInjection()); // resolution will inject the properties. IJob job = container.Resolve(); ``` -------------------------------- ### Install Stashbox via Package Manager Console Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/getting-started/introduction.md Use this command in the Package Manager Console to install the Stashbox NuGet package. ```powershell Install-Package Stashbox -Version 5.20.0 ``` -------------------------------- ### Constructor Injection Example Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/guides/service-resolution.md Demonstrates how to register and resolve a service using constructor injection. Ensure the required services (ILogger, IEventBroadcaster) are registered before resolving the dependent service (IJob). ```cs class DbBackup : IJob { private readonly ILogger logger; private readonly IEventBroadcaster eventBroadcaster; public DbBackup(ILogger logger, IEventBroadcaster eventBroadcaster) { this.logger = logger; this.eventBroadcaster = eventBroadcaster; } } container.Register(); container.Register(); container.Register(); // resolution using the available constructor. IJob job = container.Resolve(); ``` -------------------------------- ### Initialize Container with Configuration Options Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/configuration/container-configuration.md Configure container behavior during initialization using a fluent API. This example sets rules for disposable transient tracking, constructor selection, and registration behavior. ```cs var container = new StashboxContainer(options => options .WithDisposableTransientTracking() .WithConstructorSelectionRule(Rules.ConstructorSelection.PreferLeastParameters) .WithRegistrationBehavior(Rules.RegistrationBehavior.ThrowException)); ``` -------------------------------- ### Implementing a Logging Interceptor Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/advanced/decorators.md Provides an example of a LoggingInterceptor that uses Castle DynamicProxy to log method calls before and after execution, including execution duration. This demonstrates Aspect-Oriented Programming. ```cs public class LoggingInterceptor : IInterceptor { private readonly ILogger logger; public LoggingInterceptor(ILogger logger) { this.logger = logger; } public void Intercept(IInvocation invocation) { var stopwatch = new Stopwatch(); stopwatch.Start(); // log before we invoke the intercepted method. this.logger.Log($"Method begin: {invocation.GetConcreteMethod().Name}"); // call the intercepted method. invocation.Proceed(); // log after we invoked the intercepted method and print how long it ran. this.logger.Log($"Method end: {invocation.GetConcreteMethod().Name}, execution duration: {stopwatch.ElapsedMiliseconds} ms"); } } // create a DefaultProxyBuilder from the DynamicProxy library. var proxyBuilder = new DefaultProxyBuilder(); // build a proxy for the IEventProcessor interface. var eventProcessorProxy = proxyBuilder.CreateInterfaceProxyTypeWithTargetInterface( typeof(IEventProcessor), new Type[0], ProxyGenerationOptions.Default); // register the logger for LoggingInterceptor. container.Register(); // register the service that we will intercept. container.Register(); // register the interceptor. container.Register(); // register the built proxy as a decorator. container.RegisterDecorator(eventProcessorProxy); ``` -------------------------------- ### Install Stashbox via dotnet CLI Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/getting-started/introduction.md Use this command with the dotnet CLI to add Stashbox as a package dependency. ```bash dotnet add package Stashbox --version 5.20.0 ``` -------------------------------- ### Registering a service with a custom lifetime Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/guides/lifetimes.md This example shows how to register a service using a custom lifetime implementation. It assumes a 'CustomLifetime' class has been defined elsewhere, inheriting from either ExpressionLifetimeDescriptor or FactoryLifetimeDescriptor. ```cs container.Register(options => options.WithLifetime(new CustomLifetime())); ``` -------------------------------- ### Re-configure Existing Container Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/configuration/container-configuration.md Modify an existing container's configuration by calling the .Configure() method. This example enables tracking of disposable transient objects. ```cs var container = new StashboxContainer(); container.Configure(options => options.WithDisposableTransientTracking()); ``` -------------------------------- ### Registering a service instance without wire-up Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/configuration/registration-configuration.md Register an existing instance of a service using `WithInstance`. This example creates a new `ConsoleLogger` instance without enabling member/method injection. ```csharp container.Register(options => options .WithInstance(new ConsoleLogger())); ``` -------------------------------- ### Registering Multiple Decorators for Service Extension Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/advanced/decorators.md This example demonstrates how to register multiple decorators for a single service. The decorators are applied in the order they are registered, creating a pipeline of extended functionality. The first registered decorator wraps the base service, and subsequent decorators wrap the already decorated service. ```cs container.Register(); container.RegisterDecorator(); container.RegisterDecorator(); // new ValidatorProcessor(new LoggerProcessor(new GeneralProcessor())); var processor = container.Resolve(); ``` -------------------------------- ### Fluent Registration and Resolution Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/guides/basics.md Chain multiple registration calls using the fluent API for concise setup. This allows registering several services and resolving one in a single statement. ```cs var job = container.Register() .Register() .Resolve(); ``` -------------------------------- ### Registering a service with a custom initializer Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/configuration/registration-configuration.md Set a custom initializer delegate for a service registration using `WithInitializer`. This delegate will be invoked when the service is being instantiated, allowing for custom setup logic. ```csharp container.Register(options => options .WithInitializer((logger, resolver) => logger .OpenFile())); ``` -------------------------------- ### CompositionRootNotFoundException Example Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/diagnostics/validation.md Illustrates the scenario where container.ComposeAssembly is called without an ICompositionRoot implementation in the target assembly. ```csharp container.ComposeAssembly(typeof(Service).Assembly); ``` ```text No ICompositionRoot found in the given assembly: {your-assembly-name} ``` -------------------------------- ### Get all service registration mappings Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/diagnostics/utilities.md Call GetRegistrationMappings() to retrieve all registrations in the container as a collection of KeyValuePair. ```cs IEnumerable> mappings = container.GetRegistrationMappings(); ``` -------------------------------- ### Registering a Single Decorator for Event Processing Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/advanced/decorators.md This example shows how to register a validator decorator for an IEventProcessor service. The decorator adds validation logic before the main processing occurs. It demonstrates the composition of services using decorators. ```cs class Event { } class UpdateEvent : Event { } interface IEventProcessor { void ProcessEvent(Event @event); } interface IEventValidator { bool IsValid(Event @event); } class EventValidator : IEventValidator { public bool IsValid(Event @event) { /* do the actual validation. */ } } class GeneralEventProcessor : IEventProcessor { public void ProcessEvent(Event @event) { // suppose this method is processing the given event. this.DoTheActualProcessing(@event); } } class ValidatorProcessor : IEventProcessor { private readonly IEventProcessor nextProcessor; private readonly IEventValidator eventValidator; public ValidatorProcessor(IEventProcessor eventProcessor, IEventValidator eventValidator) { this.nextProcessor = eventProcessor; this.eventValidator = eventValidator; } public void ProcessEvent(Event @event) { // validate the event first. if (!this.eventValidator.IsValid(@event)) throw new InvalidEventException(); // if everything is ok, call the next processor. this.nextProcessor.ProcessEvent(@event); } } using var container = new StashboxContainer(); container.Register(); container.Register(); container.RegisterDecorator(); // new ValidatorProcessor(new GeneralEventProcessor(), new EventValidator()) var eventProcessor = container.Resolve(); // process the event. eventProcessor.ProcessEvent(new UpdateEvent()); ``` -------------------------------- ### Registering a service in a named scope Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/guides/lifetimes.md Use this to register a service that will only be resolved when a scope with the same name initiates the request. The example shows registering IJob in 'DbScope' and resolving it within that scope. ```cs container.Register(options => options .InNamedScope("DbScope")); using var scope = container.BeginScope("DbScope"); IJob job = scope.Resolve(); ``` -------------------------------- ### Resolve Unknown Types With Registration Configuration Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/advanced/special-resolution-cases.md With a registration configuration for unknown type resolution, you can control how individual registrations behave and react to resolution requests. This example maps an unregistered 'IDependency' to 'Dependency' with a singleton lifetime. ```cs interface IDependency { } class Dependency : IDependency { } class Service { public Service(IDependency dependency) { } } var container = new StashboxContainer(config => config .WithUnknownTypeResolution(options => { if(options.ServiceType == typeof(IDependency)) { options.SetImplementationType(typeof(Dependency)) .WithLifetime(Lifetimes.Singleton); } })); container.Register(); var service = container.Resolve(); ``` -------------------------------- ### Combine Auto Member Injection Rules Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/configuration/container-configuration.md Combine multiple auto-injection rules using bitwise logical operators to create a custom ruleset. This example enables injection for both private fields and properties with public setters. ```cs new StashboxContainer(options => options .WithAutoMemberInjection(Rules.AutoMemberInjectionRules.PrivateFields | Rules.AutoMemberInjectionRules.PropertiesWithPublicSetter)); ``` -------------------------------- ### Registering an instance with options Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/configuration/registration-configuration.md Register an existing instance of a service using the `WithInstance` option. This allows you to pre-instantiate services and manage their lifecycle. ```csharp container.Register(options => options .WithInstance(new DbBackup())); ``` -------------------------------- ### Resolve Service with Metadata using Metadata, ValueTuple, and Tuple Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/advanced/wrappers-resolvers.md Demonstrates how to register a service with metadata and then resolve it using Metadata<,>, ValueTuple<,>, or Tuple<,>. Use ValueTuple or Tuple to avoid direct Stashbox referencing. ```cs container.Register(options => options .WithMetadata("connection-string-to-db")); var jobWithConnectionString = container.Resolve>(); // prints: "connection-string-to-db" Console.WriteLine(jobWithConnectionString.Data); var alsoJobWithConnectionString = container.Resolve>(); // prints: "connection-string-to-db" Console.WriteLine(alsoJobWithConnectionString.Item2); var stillJobWithConnectionString = container.Resolve>(); // prints: "connection-string-to-db" Console.WriteLine(stillJobWithConnectionString.Item2); ``` -------------------------------- ### Create a Scoped Service Instance Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/guides/scopes.md Demonstrates how to register a scoped service and resolve it within a scope. Instances resolved within the same scope are guaranteed to be the same. ```cs container.RegisterScoped(); // create the scope with using so it'll be auto disposed. using (var scope = container.BeginScope()) { IJob job = scope.Resolve(); IJob jobAgain = scope.Resolve(); // job and jobAgain are created in the // same scope, so they are the same instance. } ``` -------------------------------- ### Get formatted registration diagnostics Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/diagnostics/utilities.md Use GetRegistrationDiagnostics() to obtain a human-readable representation of all service registrations in the container. The output is formatted by the RegistrationDiagnosticsInfo.ToString() method. ```cs container.Register("DbBackupJob"); container.Register(typeof(IEventHandler<>), typeof(EventHandler<>)); IEnumerable diagnostics = container.GetRegistrationDiagnostics(); diagnostics.ForEach(Console.WriteLine); // output: // IJob => DbBackup, name: DbBackupJob // IEventHandler<> => EventHandler<>, name: null ``` -------------------------------- ### ResolutionFailedException: Missing Dependency in Property/Field Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/diagnostics/validation.md Occurs when a dependency required by a property or field is not found. This example registers a Service and configures a dependency binding for its 'Dep' property. ```csharp class Service { public Dependency Dep { get; set; } } container.Register(options => options.WithDependencyBinding(s => s.Dep)); var service = container.Resolve(); ``` ```csharp Could not resolve type Namespace.Service. Unresolvable property: (Namespace.Dependency)Dep. ``` -------------------------------- ### Register Logger with Console Attribute Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/guides/service-resolution.md Register an ILogger implementation to be resolved only when the injected parameter, property, or field has the 'Console' attribute. This example demonstrates attribute-based conditional resolution. ```cs class ConsoleAttribute : Attribute { } class DbBackup : IJob { public DbBackup([Console]ILogger logger) { } } container.Register(options => options // resolve only when the injected parameter, // property or field has the 'Console' attribute .WhenHas()); container.Register(); // the container will resolve DbBackup with ConsoleLogger. IJob job = container.Resolve(); ``` -------------------------------- ### Chaining registration options Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/configuration/registration-configuration.md Demonstrates the fluent nature of the registration configuration API by chaining multiple options together. This allows for concise and readable configuration of complex registrations. ```csharp container.Register(options => options .WithName("DbBackup") .WithLifetime(Lifetimes.Singleton) .WithoutDisposalTracking()); ``` -------------------------------- ### Async Disposal of Service within Scope (Explicit DisposeAsync) Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/guides/scopes.md Asynchronously dispose a scope to trigger the asynchronous disposal of tracked instances. This example uses explicit scope.DisposeAsync(). ```cs var scope = container.BeginScope(); var disposable = scope.Resolve(); // 'disposable' will be disposed asynchronously with the scope. await scope.DisposeAsync(); ``` -------------------------------- ### Parameterized Factory Registration (1-5 Parameters) Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/configuration/registration-configuration.md Register a service using a factory delegate that accepts a specific number of pre-resolved dependencies as parameters. This allows for complex object creation logic. ```csharp // 1 parameter factory container.Register(options => options .WithFactory(logger => new UserRepository(logger)); // 2 parameters factory container.Register(options => options .WithFactory((logger, context) => new UserRepository(logger, context)); // 3 parameters factory container.Register(options => options .WithFactory((logger, context, options) => new UserRepository(logger, context, options)); // 4 parameters factory container.Register(options => options .WithFactory((logger, connection, options, validator) => new UserRepository(logger, connection, options, validator)); // 5 parameters factory container.Register(options => options .WithFactory( (logger, connection, options, validator, permissionManager) => new UserRepository(logger, connection, options, validator, permissionManager)); ``` -------------------------------- ### Dispose Service within Scope (Explicit Dispose) Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/guides/scopes.md Manually dispose a scope to trigger the disposal of tracked disposable instances. This example uses explicit scope disposal. ```cs var scope = container.BeginScope(); var disposable = scope.Resolve(); // 'disposable' will be disposed with the scope. scope.Dispose(); ``` -------------------------------- ### Post-Processing Instances with BuildUp Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/guides/service-resolution.md Employ the `BuildUp()` method to perform post-processing, such as property/field/method injection, on already constructed instances. Note that `BuildUp()` does not register the instance into the container. ```cs class DbBackup : IJob { public ILogger Logger { get; set; } } DbBackup backup = new DbBackup(); // the container fills the Logger property. container.BuildUp(backup); ``` -------------------------------- ### Registering a service for dynamic resolution Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/configuration/registration-configuration.md Configure a service for dynamic resolution using `WithDynamicResolution`. This tells the container to use a `Resolve()` call during resolution instead of a pre-built expression. ```csharp container.Register(); container.Register(options => options .WithDynamicResolution()); // new DbBackup(currentScope.Resolve()); var job = container.Resolve(); ``` -------------------------------- ### ResolutionFailedException: Missing Dependency in Constructor Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/diagnostics/validation.md Occurs when a dependency required by a constructor is not found in the resolution tree. This example shows a Service with two constructors, each requiring a different dependency. ```csharp class Service { public Service(Dependency dep) { } public Service(Dependency2 dep2) { } } container.Register(); var service = container.Resolve(); ``` ```csharp Could not resolve type Namespace.Service. Constructor Void .ctor(Dependency) found with unresolvable parameter: (Namespace.Dependency)dep. Constructor Void .ctor(Dependency2) found with unresolvable parameter: (Namespace.Dependency2)dep2. ``` -------------------------------- ### Registering a service instance with wire-up enabled Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/configuration/registration-configuration.md Register an existing instance of a service using `WithInstance` and enable member/method injection by setting `wireUp` to `true`. This allows the container to inject dependencies into the provided instance. ```csharp container.Register(options => options .WithInstance(new ConsoleLogger(), wireUp: true)); ``` -------------------------------- ### On-the-Fly Instance Activation Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/guides/service-resolution.md Use the `Activate()` method to create and dependency-inject instances of types without prior registration in the container. It supports dependency overriding and performs property/field/method injection. ```cs // use dependency injected by container. DbBackup backup = container.Activate(); // override the injected dependency. DbBackup backup = container.Activate(new ConsoleLogger()); ``` ```cs // use dependency injected by container. object backup = container.Activate(typeof(DbBackup)); // override the injected dependency. object backup = container.Activate(typeof(DbBackup), new ConsoleLogger()); ``` -------------------------------- ### Dispose Service within Scope (Using Statement) Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/guides/scopes.md Services implementing IDisposable or IAsyncDisposable are tracked and disposed when the scope is disposed. This example shows disposal using a 'using' statement. ```cs using (var scope = container.BeginScope()) { var disposable = scope.Resolve(); } // 'disposable' will be disposed when // the using statement ends. ``` -------------------------------- ### Apply Member Selection Filter for Auto Injection Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/configuration/container-configuration.md Provide a custom member selection logic to control which members are auto-injected. This example excludes members of type ILogger from being auto-injected. ```cs new StashboxContainer(options => options .WithAutoMemberInjection( filter: member => member.Type != typeof(ILogger))); ``` -------------------------------- ### Register Service with Singleton Lifetime (Shorter Form) Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/guides/lifetimes.md Registers a service with the Singleton lifetime using the RegisterSingleton shortcut. A single instance will be reused for all requests. ```cs container.RegisterSingleton(); ``` -------------------------------- ### InjectionMethod Attribute for Initialization Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/guides/service-resolution.md Use the InjectionMethod attribute to mark a method that Stashbox should call after the service has been instantiated. This method can be used for setup or initialization logic, potentially injecting dependencies. ```cs class DbBackup : IJob { [InjectionMethod] public void Initialize([Dependency("Console")]ILogger logger) { this.logger.Log("Initializing."); } } container.Register("Console"); container.Register("File"); container.Register(); // the container will call DbBackup's Initialize method. IJob job = container.Resolve(); ``` -------------------------------- ### Register Transient Service with Shortcut Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/guides/basics.md Use this shortcut to register a service with the default transient lifetime. The service will be instantiated every time it is resolved. ```csharp container.Register(); IJob job = container.Resolve(); ``` -------------------------------- ### Wire Up Instance with Generic API Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/guides/basics.md Register an instance and allow Stashbox to perform property/field injection upon resolution. This is similar to instance registration but enables dependency injection. ```cs container.WireUp(new DbBackup()); IJob job = container.Resolve(); ``` -------------------------------- ### Named Service Registration and Resolution Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/getting-started/glossary.md Demonstrates how to register a service with a specific name and then resolve it using that name. This is useful for differentiating between multiple registrations of the same service type. ```cs container.Register("Example"); // the named request. var service = container.Resolve("Example"); ``` -------------------------------- ### Registering a service that defines its own named scope Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/guides/lifetimes.md This registers a service that defines its own scope, allowing other services to be registered within that defined scope. The example shows DbJobExecutor defining a scope and IJob being registered within it. ```cs container.Register(options => options .DefinesScope()); ontainer.Register(options => options .InScopeDefinedBy()); // the executor will begin a new scope within itself // when it gets resolved and DbBackup will be selected // and attached to that scope instead. using var scope = container.BeginScope(); DbJobExecutor executor = scope.Resolve(); ``` -------------------------------- ### Conditional registration based on service type Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/configuration/registration-configuration.md Use `HasServiceType` within a batch registration configuration to apply specific registration options based on the service type. This example applies `WithScopedLifetime` if the service type is `IService2`. ```csharp container.RegisterAssemblyContaining(configurator: options => { if (options.HasServiceType()) options.WithScopedLifetime(); }); ``` -------------------------------- ### Registering and Resolving with Child Containers Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/advanced/child-containers.md Demonstrates how services are resolved from parent and child containers, highlighting how child registrations override parent ones for the same service type. Use this to manage distinct dependency sets within an application hierarchy. ```csharp interface IDependency {} class B : IDependency {} class C : IDependency {} class A { public A(IDependency dependency) { } } using (var container = new StashboxContainer()) { // register 'A' into the parent container. container.Register(); // register 'B' as a dependency into the parent container. container.Register(); var child = container.CreateChildContainer() // register 'C' as a dependency into the child container. child.Register(); // 'A' is resolved from the parent and gets // 'C' as IDependency because the resolution // request was initiated on the child. A fromChild = child.Resolve(); // 'A' gets 'B' as IDependency because the // resolution request was initiated on the parent. A fromParent = container.Resolve(); } // using will dispose the parent along with the child. ``` -------------------------------- ### Register Service with Injection Parameters Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/guides/advanced-registration.md Registers a service and specifies injection parameters for its constructor or properties. Use this to provide pre-evaluated dependencies during resolution. ```cs container.Register(options => options .WithInjectionParameter("logger", new ConsoleLogger()) .WithInjectionParameter("eventBroadcaster", new MessageBus()); // the injection parameters will be passed to DbBackup's constructor. IJob backup = container.Resolve(); ``` -------------------------------- ### Register Service with Initializer and Finalizer Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/guides/advanced-registration.md Register a service and specify delegates to be called after instantiation (initializer) and before disposal (finalizer). ```csharp container.Register(options => options // delegate that called right after instantiation. .WithInitializer((logger, resolver) => logger.OpenFile()) // delegate that called right before the instance's disposal. .WithFinalizer(logger => logger.CloseFile())); ``` -------------------------------- ### Registering a service in a named scope defined by another service Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/guides/lifetimes.md This registers a service to be used within a named scope that is defined by another service. The example shows DbJobExecutor defining a scope named 'DbScope' and IJob being registered within that same named scope. ```cs container.Register(options => options .DefinesScope("DbScope")); ontainer.Register(options => options .InNamedScope("DbScope")); // the executor will begin a new scope within itself // when it gets resolved and DbBackup will be selected // and attached to that scope instead. using var scope = container.BeginScope(); DbJobExecutor executor = scope.Resolve(); ``` -------------------------------- ### Compose All Composition Roots in an Assembly Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/guides/advanced-registration.md Automatically finds and executes all available `ICompositionRoot` implementations within a specified assembly. This is useful for discovering and wiring up multiple entry points. ```cs // compose every root in the given assembly. container.ComposeAssembly(typeof(IServiceA).Assembly); ``` -------------------------------- ### Resolve Unknown Types Without Registration Configuration Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/advanced/special-resolution-cases.md When unknown type resolution is enabled without a specific registration configuration, the container can resolve non-interface and non-abstract unknown types by creating implicit registrations. This example shows implicit registration for 'Dependency' and its injection into 'Service'. ```cs class Dependency { } class Service { public Service(Dependency dependency) { } } var container = new StashboxContainer(config => config .WithUnknownTypeResolution()); container.Register(); var service = container.Resolve(); ``` -------------------------------- ### Resolving Services from Named Scopes Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/guides/scopes.md Demonstrates how to resolve services registered within named scopes. It shows creating parent and sub-scopes, including named sub-scopes, and resolving services accordingly. Also covers resolving from unnamed scopes and the expected outcomes. ```cs using (var dbScope = container.BeginScope("DbScope")) { // DbBackup and DbCleanup will be returned. IEnumerable jobs = dbScope.ResolveAll(); // create a sub-scope of dbScope. using var sub = dbScope.BeginScope(); // DbBackup and DbCleanup will be returned from the named parent scope. IEnumerable jobs = sub.ResolveAll(); // create a named sub-scope. using var namedSub = dbScope.BeginScope("DbSubScope"); // DbIndexRebuild will be returned from the named sub-scope. IEnumerable jobs = namedSub.ResolveAll(); } using (var storageScope = container.BeginScope("StorageScope")) { // StorageCleanup will be returned. IJob job = storageScope.Resolve(); } // create a common scope without a name. using (var unNamed = container.BeginScope()) { // empty result as there's no service registered without named scope. IEnumerable jobs = unNamed.ResolveAll(); // throws an exception because there's no unnamed service registered. IJob job = unNamed.Resolve(); } ``` -------------------------------- ### Factory Instantiation with Constructor Selection Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/guides/advanced-registration.md When a service has multiple constructors, the container selects the one with matching parameters passed to the factory, respecting constructor selection rules. ```cs class Service { public Service(int number) { } public Service(string text) { } } container.Register(); // create the factory with an int input parameter. var func = constainer.Resolve>(); // the constructor with the int param // is used for instantiation. var service = func(2); ``` -------------------------------- ### Registering Open-Generic Decorators Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/advanced/decorators.md Demonstrates how to register an open-generic decorator to extend open-generic services. This allows for conditional logic or additional processing before or after the decorated service's execution. ```csharp interface IEventProcessor { void ProcessEvent(TEvent @event); } class GeneralEventProcessor : IEventProcessor { public void ProcessEvent(TEvent @event) { /* suppose this method is processing the given event.*/ } } class ValidatorProcessor : IEventProcessor { private readonly IEventProcessor nextProcessor; public ValidatorProcessor(IEventProcessor eventProcessor) { this.nextProcessor = eventProcessor; } public void ProcessEvent(TEvent @event) { // validate the event first. if (!this.IsValid(@event)) throw new InvalidEventException(); // if everything is ok, call the next processor. this.nextProcessor.ProcessEvent(@event); } } using var container = new StashboxContainer(); container.Register(typeof(IEventProcessor<>), typeof(GeneralEventProcessor<>)); container.RegisterDecorator(typeof(IEventProcessor<>), typeof(ValidatorProcessor<>)); // new ValidatorProcessor(new GeneralEventProcessor()) var eventProcessor = container.Resolve>(); // process the event. eventProcessor.ProcessEvent(new UpdateEvent()); ``` -------------------------------- ### Re-building Singletons in Child Containers Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/advanced/child-containers.md Shows how to enable singleton re-instantiation in child containers using container options. This allows re-built singletons to utilize overridden dependencies specific to the child container. ```csharp interface IDependency {} class B : IDependency {} class C : IDependency {} class A { public A(IDependency dependency) { } } using (var container = new StashboxContainer(options => options.WithReBuildSingletonsInChildContainer())) { // register 'A' as a singleton into the parent container. container.RegisterSingleton(); // register 'B' as a dependency into the parent container. container.Register(); // 'A' gets 'B' as IDependency and will be stored // in the parent container as a singleton. A fromParent = container.Resolve(); var child = container.CreateChildContainer(); // register 'C' as a dependency into the child container. child.Register(); // a new 'A' singleton will be created in // the child container with 'C' as IDependency. A fromChild = child.Resolve(); } // using will dispose the parent along with the child. ``` -------------------------------- ### Resolve Service with Identifier using KeyValuePair and ReadOnlyKeyValue Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/advanced/wrappers-resolvers.md Demonstrates registering services with unique identifiers (names) and resolving them using KeyValuePair or ReadOnlyKeyValue. Use KeyValuePair to avoid direct Stashbox referencing. ```cs container.Register("FirstServiceId"); container.Register("SecondServiceId"); container.Register(); var serviceKeyValue1 = container .Resolve>("FirstServiceId"); // prints: "FirstServiceId" Console.WriteLine(serviceKeyValue1.Key); var serviceKeyValue2 = container .Resolve>("SecondServiceId"); // prints: "SecondServiceId" Console.WriteLine(serviceKeyValue2.Key); ``` -------------------------------- ### Factory Registration with Dependency Resolver (1 Parameter) Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/configuration/registration-configuration.md Register a service using a factory delegate that accepts the IDependencyResolver as a parameter to resolve other dependencies. ```csharp container.Register(options => options .WithFactory((logger, resolver) => new UserRepository(logger, resolver.Resolve()))); ``` -------------------------------- ### Wire Up Instance with Runtime Type API Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/guides/basics.md Register an instance using its runtime type and enable dependency injection. Stashbox will perform property/field injection on the instance during resolution. ```cs container.WireUp(new DbBackup(), typeof(IJob)); object job = container.Resolve(typeof(IJob)); ``` -------------------------------- ### Register Self-Implementation Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/getting-started/glossary.md Register a service where the service and implementation types are the same. This is a shorthand for container.Register(). ```csharp container.Register(); ``` -------------------------------- ### Define and Compose a Single Composition Root Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/guides/advanced-registration.md Defines a custom composition root implementation and registers it with the container. Use this to explicitly wire up dependencies for a specific component or entry point. ```cs class ExampleRoot : ICompositionRoot { public ExampleRoot(IDependency rootDependency) { } public void Compose(IStashboxContainer container) { container.Register(); container.Register(); } } ``` ```cs // compose a single root. container.ComposeBy(); ``` -------------------------------- ### Creating and Retrieving Child Containers by Identifier Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/advanced/child-containers.md Shows how to create a child container with a specific identifier and later retrieve it using the parent container. This is useful for managing and accessing specific child container instances by name. ```csharp using var container = new StashboxContainer(); container.CreateChildContainer("child"); // ... var child = container.GetChildContainer("child"); ``` -------------------------------- ### Implementing Composite Pattern with Decorators Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/advanced/decorators.md Shows how to use decorators to implement the Composite pattern, enabling multiple instances of a service to be treated as a single unit. This is achieved by registering a decorator that depends on a collection of the same service. ```csharp public class CompositeValidator : IEventValidator { private readonly IEnumerable> validators; public CompositeValidator(IEnumerable> validators) { this.validators = validators; } public bool IsValid(TEvent @event) { return this.validators.All(validator => validator.IsValid(@event)); } } container.Register(typeof(IEventValidator<>), typeof(EventValidator<>)); container.Register(typeof(IEventValidator<>), typeof(AnotherEventValidator<>)); container.RegisterDecorator(typeof(IEventValidator<>), typeof(CompositeValidator<>)); ``` -------------------------------- ### Resolve All Services with Identifiers using KeyValuePair Array Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/advanced/wrappers-resolvers.md Illustrates how to resolve all registered services of a given type along with their identifiers by requesting an array of KeyValuePair. Services without an identifier will have a null key. ```cs // ["FirstServiceId": Service1, "SecondServiceId": Service2, null: Service3 ] var servicesWithKeys = container.Resolve[]>(); ``` -------------------------------- ### Implementing a custom lifetime using FactoryLifetimeDescriptor Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/guides/lifetimes.md This demonstrates how to create a custom lifetime by inheriting from FactoryLifetimeDescriptor. The ApplyLifetime method is overridden to manage lifetime based on a pre-compiled factory delegate for service creation. ```cs class CustomLifetime : FactoryLifetimeDescriptor { protected override Expression ApplyLifetime( Func factory, // The factory used for service creation ServiceRegistration serviceRegistration, ResolutionContext resolutionContext, Type requestedType) { // Lifetime managing functionality } } ``` -------------------------------- ### Select Constructor by Arguments Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/configuration/registration-configuration.md Use WithConstructorByArguments to select a constructor and provide specific argument instances to invoke it. This allows for direct control over constructor invocation during resolution. ```csharp container.Register(options => options .WithConstructorByArguments(new ConsoleLogger())); ``` -------------------------------- ### Filter Services by Metadata using ValueTuple Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/advanced/wrappers-resolvers.md Shows how to register multiple services with different metadata and then filter them by requesting an array of ValueTuple. This allows for selective resolution based on metadata type. ```cs container.Register(options => options .WithMetadata("meta-1")); container.Register(options => options .WithMetadata("meta-2")); container.Register(options => options .WithMetadata(5)); // the result is: [Service1, Service2] var servicesWithStringMetadata = container.Resolve[]>(); // the result is: [Service3] var servicesWithIntMetadata = container.Resolve[]>(); ``` -------------------------------- ### Add Instance to Scope Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/guides/scopes.md Add an already instantiated service to a scope. The instance's lifetime will be tracked by the given scope. ```cs using var scope = container.BeginScope(); scope.PutInstanceInScope(new DbBackup()); ``` -------------------------------- ### Registering a Singleton Decorator Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/advanced/decorators.md Demonstrates how to register a decorator with a Singleton lifetime, which overrides the decorated service's lifetime. The decorator's lifetime is applied to the wrapped service. ```cs container.Register(); // singleton decorator will change the transient // decorated service's lifetime to singleton. container.RegisterDecorator(options => options.WithLifetime(Lifetimes.Singleton)); // Singleton[new ValidatorProcessor()](Transien[new GeneralEventProcessor()]) var processor = container.Resolve(); ``` -------------------------------- ### Creating Nested Child Containers Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/advanced/child-containers.md Demonstrates the creation of a hierarchical tree of containers by chaining the `.CreateChildContainer()` method. This allows for complex nested dependency injection structures. ```csharp using var container = new StashboxContainer(); var child1 = container.CreateChildContainer(); var child2 = child1.CreateChildContainer(); ``` -------------------------------- ### Service Interfaces and Implementations Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/getting-started/introduction.md Defines interfaces for logging, event broadcasting, and job execution, along with their concrete implementations. This showcases dependency on interfaces for better decoupling. ```csharp public interface IJob { void DoTheJob(); } public interface ILogger { void Log(string message); } public interface IEventBroadcaster { void Broadcast(IEvent @event); } public class ConsoleLogger : ILogger { public void Log(string message) => Console.WriteLine(message); } public class MessageBus : IEventBroadcaster { private readonly ILogger logger; public MessageBus(ILogger logger) { this.logger = logger; } void Broadcast(IEvent @event) { this.logger.Log($"Sending event to bus: {@event.Name}"); // Do the actual event broadcast. } } public class DbBackup : IJob { private readonly ILogger logger; private readonly IEventBroadcaster eventBroadcaster; public DbBackup(ILogger logger, IEventBroadcaster eventBroadcaster) { this.logger = logger; this.eventBroadcaster = eventBroadcaster; } public void DoTheJob() { this.logger.Log("Backing up!"); // Do the actual backup. this.eventBroadcaster.Broadcast(new DbBackupCompleted()); } } ``` -------------------------------- ### Registering a service with metadata Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/configuration/registration-configuration.md Attach custom metadata to a service registration using the `WithMetadata` option. The metadata can be accessed upon resolution of the service. ```csharp container.Register(options => options .WithMetadata(connectionString)); var jobWithConnectionString = container.Resolve>(); Console.WriteLine(jobWithConnectionString.Item2); // prints the connection string. ``` -------------------------------- ### Set Multiple Injection Parameters Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/configuration/registration-configuration.md Configure multiple injection parameters for a service registration using a collection of key-value pairs. ```csharp container.Register(options => options .WithInjectionParameters(new KeyValuePair("logger", new ConsoleLogger())); ``` -------------------------------- ### Batch Register Instances Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/guides/basics.md Register multiple instances for the same service type in a single operation. All registered instances can be resolved using `ResolveAll`. ```cs container.RegisterInstances(new DbBackup(), new StorageCleanup()); IEnumerable jobs = container.ResolveAll(); ``` -------------------------------- ### Registering a Decorator with Wrappers Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/advanced/decorators.md Shows how to register a decorator that also utilizes wrappers. This allows for additional functionality to be applied to the decorated service, such as creating a Func. ```cs container.Register(); container.RegisterDecorator(); // () => new ValidatorProcessor(new GeneralEventProcessor()) var processor = container.Resolve>(); ``` -------------------------------- ### Add Stashbox via PackageReference Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/getting-started/introduction.md Include this XML snippet in your .csproj file's package references to add Stashbox. ```xml ``` -------------------------------- ### Register Instance Without Disposal Tracking Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/guides/basics.md Register an external instance without Stashbox tracking its disposal. Use the `withoutDisposalTracking` parameter for this. ```cs var job = new DbBackup(); container.RegisterInstance(job, withoutDisposalTracking: true); // resolvedJob and job are the same. IJob resolvedJob = container.Resolve(); ``` -------------------------------- ### Nested Scopes and Instance Isolation Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/guides/scopes.md Illustrates the creation of nested scopes and how service instances are isolated between parent and child scopes. Instances resolved in a sub-scope are distinct from those in the parent scope. ```cs container.RegisterScoped(); using (var parent = container.BeginScope()) { IJob job = parent.Resolve(); IJob jobAgain = parent.Resolve(); // job and jobAgain are created in the // same scope, so they are the same instance. // create a sub-scope. using var sub = parent.BeginScope(); IJob subJob = sub.Resolve(); // subJob is a new instance created in the sub-scope, // differs from either job and jobAgain. } ``` -------------------------------- ### Select Constructor by Argument Types Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/configuration/registration-configuration.md Use WithConstructorByArgumentTypes to specify which constructor to use based on the types of its arguments. This is helpful when a service has multiple constructors with different parameter types. ```csharp container.Register(options => options .WithConstructorByArgumentTypes(typeof(ILogger))); ``` -------------------------------- ### Bind Implementation to All Implemented Types Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/guides/advanced-registration.md Register a DbBackup class to be resolvable by all interfaces it implements (IJob, IScheduledJob) as well as its own type. ```cs container.Register(options => options .AsImplementedTypes()); IJob job = container.Resolve(); // DbBackup IScheduledJob job = container.Resolve(); // DbBackup DbBackup job = container.Resolve(); // DbBackup ``` -------------------------------- ### Set Constructor Selection Rule to Prefer Most Parameters Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/configuration/container-configuration.md Configure the container to prefer the constructor with the most parameters when resolving dependencies. This is the default behavior. ```cs new StashboxContainer(options => options .WithConstructorSelectionRule( Rules.ConstructorSelection.PreferMostParameters)); ``` -------------------------------- ### Register Parameter-less Factory Delegate Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/guides/advanced-registration.md Bind a parameter-less factory delegate to a registration. The container invokes this delegate to instantiate the service. ```cs container.Register(options => options .WithFactory(() => new ConsoleLogger())); // the container uses the factory for instantiation. IJob job = container.Resolve(); ``` -------------------------------- ### Custom Constructor Selection Logic Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/configuration/registration-configuration.md Provide custom logic to the WithConstructorSelectionRule to define your own constructor ordering strategy. This allows for highly specific constructor selection based on application needs. ```csharp options.WithConstructorSelectionRule( constructors => { /* custom constructor sorting logic */ }) ``` -------------------------------- ### Register Factory with External Dependency Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/guides/advanced-registration.md Delegate factories are useful when service instantiation depends on runtime values like connection strings, which are not available at resolution time. ```cs container.Register(options => options .WithFactory(logger => new DbBackup(Configuration["DbConnectionString"], logger))); ``` -------------------------------- ### Registering a service with a custom finalizer Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/configuration/registration-configuration.md Set a custom cleanup delegate for a service registration using `WithFinalizer`. This delegate will be invoked when the scope or container holding the instance is disposed. ```csharp container.Register(options => options .WithFinalizer(logger => logger .CloseFile())); ``` -------------------------------- ### Controlling Service Resolution with ResolutionBehavior Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/advanced/child-containers.md Demonstrates how to use ResolutionBehavior to specify which containers (current, parent, or both) can participate in service resolution. Useful for fine-grained control over dependency injection scope. ```csharp interface IService {} class A : IService {} class B : IService {} using (var container = new StashboxContainer()) { // register 'A' into the parent container. container.Register(); var child = container.CreateChildContainer() // register 'B' into the child container. child.Register(); // 'A' is resolved because only parent // can participate in the resolution request. IService withParent = child.Resolve(ResolutionBehavior.Parent); // Only 'B' is in the collection because // only the caller container can take part // in the resolution request. IEnumerable allWithCurrent = child.Resolve>(ResolutionBehavior.Current); // Both 'A' and 'B' is in the collection // because both the parent and the caller container // participates in the resolution request. IEnumerable all = child.Resolve>(ResolutionBehavior.Current | ResolutionBehavior.Parent); } // using will dispose the parent along with the child. ``` -------------------------------- ### Decorating Multiple Services with One Decorator Class Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/advanced/decorators.md Illustrates how a single decorator class can be used to add functionality to multiple interfaces. This is useful for applying common logic, like validation, before operations on different but related services. ```csharp public class EventValidator : IEventProcessor, IEventPublisher { private readonly IEventProcessor processor; private readonly IEventPublisher publisher; private readonly IEventValidator validator; public CompositeValidator(IEventProcessor processor, IEventPublisher publisher, IEventValidator validator) { this.processor = processor; this.publisher = publisher; this.validator = validator; } public void ProcessEvent(TEvent @event) { // validate the event first. if (!this.validator.IsValid(@event)) throw new InvalidEventException(); // if everything is ok, call the processor. this.processor.ProcessEvent(@event); } public void PublishEvent(TEvent @event) { // validate the event first. if (!this.validator.IsValid(@event)) throw new InvalidEventException(); // if everything is ok, call the publisher. this.publisher.PublishEvent(@event); } } container.Register(typeof(IEventProcessor<>), typeof(EventProcessor<>)); container.Register(typeof(IEventPublisher<>), typeof(EventPublisher<>)); container.Register(typeof(IEventValidator<>), typeof(EventValidator<>)); // without specifying the interface type, the container binds this registration to all of its implemented types container.RegisterDecorator(typeof(EventValidator<>)); ``` -------------------------------- ### Register Service with Scoped Lifetime (Shorter Form) Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/guides/lifetimes.md Registers a service with the Scoped lifetime using the RegisterScoped shortcut. A new instance is created per scope. ```cs container.RegisterScoped(); using var scope = container.BeginScope(); IJob job = scope.Resolve(); ``` -------------------------------- ### Resolve Multiple Jobs and Loggers Source: https://github.com/z4kn4fein/stashbox/blob/master/docs/docs/guides/advanced-registration.md Demonstrates resolving all instances of a specific interface (IJob) and attempting to resolve a logger. Note that some resolutions might result in errors if the dependency is not registered. ```csharp IEnumerable jobs = container.ResolveAll(); // 2 items ILogger logger = container.Resolve(); // error, not found IJob job = container.Resolve(); // StorageCleanup DbBackup backup = container.Resolve(); // error, not found ```