### Example: Registering and Using Interceptor with LinFu Source: https://github.com/dadhi/dryioc/blob/master/docs/DryIoc.Docs/Interception.md Demonstrates how to register an interceptor for an interface `IBar` using `BarInvokeWrapper` and a `BarLogger`. This example shows the full setup within a test case. ```cs public class Register_and_use_interceptor_with_LinFu { public interface IBar { void Greet(); } public class Bar : IBar { public void Greet() { } } public class BarLogger { public List LogLines = new List(); public void Log(string line) => LogLines.Add(line); } public class BarInvokeWrapper : InvokeWrapperBase { private readonly BarLogger _logger; public BarInvokeWrapper(IBar bar, BarLogger logger) : base(bar) { _logger = logger; } public override object DoInvoke(InvocationInfo info) { _logger.Log($"Invoking method: {info.TargetMethod.Name}"); // may be optimized, because we know the actual `Target` object here. //if (info.TargetMethod.Name == nameof(IBar.Greet)) // Target.Greet(); return base.DoInvoke(info); } } [Test] public void Example() { var container = new Container(); container.Register(); container.Register(Reuse.Singleton); container.Register(); container.InterceptInvocation(); var foo = container.Resolve(); foo.Greet(); // examine that logging indeed was hooked up var logger = container.Resolve(); Assert.AreEqual("Invoking method: Greet", logger.LogLines[0]); } } ``` -------------------------------- ### Emulating openResolutionScope setup manually Source: https://github.com/dadhi/dryioc/blob/master/docs/DryIoc.Docs/ReuseAndScopes.md Shows how to manually open a resolution scope using `container.OpenScope` to achieve the same reuse behavior as `openResolutionScope: true` setup. Useful for testing. ```csharp public class Emulating_openResolutionScope_setup { [Test] public void Example() { var container = new Container(); container.Register(Reuse.ScopedToService()); // huh, scope to itself explicitly - not needed / implied when using `openResolutionScope: true` container.Register(); container.Register(Reuse.ScopedToService()); var scopeNameForFoo = ResolutionScopeName.Of(); using var fooScope = container.OpenScope(scopeNameForFoo); var foo = fooScope.Resolve(); Assert.AreSame(foo.Sub, foo.Dep.Sub); } class Foo { public SubDependency Sub { get; } public Dependency Dep { get; } public Foo(SubDependency sub, Dependency dep) { Sub = sub; Dep = dep; } } class Dependency { public SubDependency Sub { get; } public Dependency(SubDependency sub) { Sub = sub; } } class SubDependency { } } ``` -------------------------------- ### Registering and Using an Interceptor Source: https://github.com/dadhi/dryioc/blob/master/docs/DryIoc.Docs/Interception.md Demonstrates how to register a service and its interceptor, then use the custom Intercept extension method to link them. This example shows the full setup for interception. ```csharp public class Register_and_use_interceptor { public interface IFoo { void Greet(); } public class Foo : IFoo { public void Greet() { } } [Test] public void Example() { var container = new Container(); container.Register(); container.Register(Reuse.Singleton); container.Intercept(); var foo = container.Resolve(); foo.Greet(); // examine that logging indeed was hooked up var logger = container.Resolve(); Assert.AreEqual("Invoking method: Greet", logger.LogLines[0]); } } ``` -------------------------------- ### Manual Object Creation Example Source: https://github.com/dadhi/dryioc/blob/master/docs/DryIoc.Docs/Home.md Illustrates manual instantiation of a client and its service dependency, highlighting the hard-wired nature of this approach. ```csharp class Created_manually { [Test] public void Example() { IClient client = new SomeClient(new SomeService()); } } ``` -------------------------------- ### RegisterMany Examples with DryIoc Container Source: https://github.com/dadhi/dryioc/blob/master/docs/DryIoc.Docs/RegisterResolve.md Demonstrates various ways to use RegisterMany for registering services with different reuse policies and conditions. Includes setup for tracking disposable transients. ```csharp public class RegisterMany_examples { public interface X { } public interface Y { } public class A : X, Y { } public class B : X, IDisposable { public void Dispose() { } } public static A CreateA() => new A(); [Test] public void Example() { // Allows registration of B which implements IDisposable as Transient, which is default `RegisterMany` reuse. var container = new Container(rules => rules .WithTrackingDisposableTransients()); // Registers X, Y and A itself with A implementation container.RegisterMany(); // Registers only X and Y, but not A itself container.RegisterMany(serviceTypeCondition: type => type.IsInterface); // X, Y, A are sharing the same singleton container.RegisterMany(Reuse.Singleton); Assert.AreSame(container.Resolve(), container.Resolve()); // Registers X, Y with A and X with B // IDisposable is too general to be considered as a service type, // see the full list of excluded types after example below. container.RegisterMany( new[] { typeof(A), typeof(B) }, serviceTypeCondition: type => type.IsInterface); // Registers only X with A and X with B container.RegisterMany( new[] { typeof(A), typeof(B) }, serviceTypeCondition: type => type == typeof(X)); // The same as above if A and B in the same assembly. // Plus registers the rest of the types from assembly of A. container.RegisterMany(new[] { typeof(A).Assembly }, type => type == typeof(X)); // Made.Of expression is supported too container.RegisterMany(Made.Of(() => CreateA())); // Explicit about what services to register container.RegisterMany(new[] { typeof(X), typeof(Y) }, typeof(A)); // Provides full control to you container.RegisterMany(new[] { typeof(A).Assembly }, getServiceTypes: implType => implType.GetImplementedServiceTypes(), getImplFactory: implType => ReflectionFactory.Of(implType, implType.IsAssignableTo() ? Reuse.Scoped : Reuse.Transient, FactoryMethod.ConstructorWithResolvableArguments)); } } ``` -------------------------------- ### Basic Wrapper Example with Lazy Source: https://github.com/dadhi/dryioc/blob/master/docs/DryIoc.Docs/Wrappers.md Demonstrates the basic usage of wrappers, specifically Lazy, where Lazy is available without explicit registration. It shows how a service B can depend on a Lazy. ```csharp namespace DryIoc.Docs; using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using DryIoc; using NUnit.Framework; // ReSharper disable UnusedVariable public class Wrapper_example { [Test] public void Example() { var container = new Container(); // The actual service registrations container.Register(); container.Register(); // Lazy is available without registration! container.Resolve(); } class A { } class B { public B(Lazy a) { } } } ``` -------------------------------- ### Registering IStartable Components in DryIoc Source: https://github.com/dadhi/dryioc/blob/master/docs/DryIoc.Docs/FaqAutofacMigration.md This snippet shows how to resolve and start IStartable components, similar to Autofac's startable components. It filters registrations for IStartable types and executes their Start method. ```csharp var ignored = container.GetServiceRegistrations() .Where(r => (r.Factory.ImplementationType ?? r.ServiceType).IsAssignableTo(typeof(IStartable))) .OrderBy(r => r.FactoryRegistrationOrder) .GroupBy(r => r.FactoryRegistrationOrder, (f, r) => r.First()) .Select(r => ((IStartable)container.Resolve(r.ServiceType, r.OptionalServiceKey)).Start()); ``` -------------------------------- ### Child Container Example: Parent and Child Interactions Source: https://github.com/dadhi/dryioc/blob/master/docs/DryIoc.Docs/KindsOfChildContainer.md Demonstrates registering services in parent and child containers, resolving them, and how default service keys affect visibility and resolution. ```csharp public class ChildExample { public class A { public D D; public A(D d) => D = d; } public class A1 { public D D; public A1(D d) => D = d; } public class B { public D D; public B(D d) => D = d; } public class D { } public class D1 : D { } public class D2 : D { } [Test] public void Parent_and_child() { using var parent = new Container(); parent.Register(); parent.Register(); var a = parent.Resolve(); Assert.IsInstanceOf(a.D); var childServiceKey = "@child"; using var child = parent.CreateChild(RegistrySharing.Share, childServiceKey); child.Register(); child.Register(); var b = child.Resolve(); Assert.IsInstanceOf(b.D); // Register later into the parent, resolve from the existing child parent.Register(); var a1 = child.Resolve(); Assert.IsInstanceOf(a1.D); // The parent registration is still available if needed through explicit service key, // as well as parent may request the child service if needed via explicit key var parentD = child.Resolve(serviceKey: DefaultKey.Value); var childD = parent.Resolve(serviceKey: childServiceKey); Assert.IsInstanceOf(parentD); Assert.IsInstanceOf(childD); } } ``` -------------------------------- ### DryIoc Facade Example for Testing Source: https://github.com/dadhi/dryioc/blob/master/docs/DryIoc.Docs/KindsOfChildContainer.md Demonstrates using `CreateFacade` to isolate test registrations. A `Client` resolves an `IService`, which is initially a `ProdService` but overridden to `TestService` in the facade. ```cs public class FacadeExample { public interface IService { } public class ProdService : IService { } public class TestService : IService { } public class Client { public IService Service { get; } public Client(IService service) => Service = service; } [Test]public void Facade_for_tests() { var container = new Container(); container.Register(); container.Register(); var testFacade = container.CreateFacade(); testFacade.Register(); var client = testFacade.Resolve(); Assert.IsInstanceOf(client.Service); } } ``` -------------------------------- ### Parallel Singleton Resolution Example Source: https://github.com/dadhi/dryioc/blob/master/docs/DryIoc.Docs/ThreadSafety.md Demonstrates how DryIoc ensures a singleton service is created only once, even when resolved concurrently from multiple threads. This example highlights the need for locking during reused service creation. ```cs public class Resolving_singleton_in_parallel { [Test] public void Example() { var container = new Container(); container.Register(Reuse.Singleton); Task.WaitAll( Task.Run(() => container.Resolve()), Task.Run(() => container.Resolve()), Task.Run(() => container.Resolve()) ); Assert.AreEqual(1, A.InstanceCount); } public class A { public static int InstanceCount; public A() { ++InstanceCount; } } } ``` -------------------------------- ### Using statements for DryIoc documentation Source: https://github.com/dadhi/dryioc/blob/master/docs/DryIoc.Docs/Decorators.md Essential using statements for DryIoc documentation examples. ```cs namespace DryIoc.Docs; using System; using System.Collections.Generic; using System.Linq; using NUnit.Framework; using DryIoc; using DryIoc.FastExpressionCompiler.LightExpression; // light alternative to the System.Linq.Expressions // ReSharper disable UnusedParameter.Local ``` -------------------------------- ### Example of reusing dependency as a variable Source: https://github.com/dadhi/dryioc/blob/master/docs/DryIoc.Docs/ReuseAndScopes.md Illustrates how a dependency can be manually managed and reused like a variable within a service and its nested dependencies. ```csharp class Example_of_reusing_dependency_as_variable { Foo Create() { var sub = new SubDependency(); return new Foo(sub, new Dependency(sub)); } class Foo { public Foo(SubDependency sub, Dependency dep) { } } class Dependency { public Dependency(SubDependency sub) { } } class SubDependency { } } ``` -------------------------------- ### Basic MEFAttributedModel Example Source: https://github.com/dadhi/dryioc/blob/master/docs/DryIoc.Docs/Extensions/MefAttributedModel.md Demonstrates basic usage of WithMefAttributedModel to configure the container and register exported types. The container automatically handles injection of dependencies marked with Import attributes. ```cs namespace DryIoc.Docs; using System; using System.ComponentModel.Composition; // for the Export and Import attributes using DryIocAttributes; using DryIoc.MefAttributedModel; using DryIoc; using NUnit.Framework; public class Basic_example { [Test] public void Example() { // instructs to use the Import for DI when they found but it is not needed to use the Export var container = new Container().WithMefAttributedModel(); // registers exported types container.RegisterExports(typeof(Foo), typeof(Bar)); // or via assemblies // container.RegisterExports(new[] { typeof(Foo).GetAssembly() }); // creates Foo with injected Bar var foo = container.Resolve(); Assert.IsNotNull(foo); } public interface IFoo { } [Export(typeof(IFoo))] public class Foo : IFoo { public Foo([Import("some-key")] Bar bar) { } } [Export("some-key")] public class Bar { } } ``` -------------------------------- ### Basic Container Creation Source: https://github.com/dadhi/dryioc/blob/master/docs/DryIoc.Docs/CreatingAndDisposingContainer.md The simplest way to create a DryIoc container. Use this for standard dependency injection setups. ```csharp namespace DryIoc.Docs; using System; using DryIoc; using NUnit.Framework; // ReSharper disable UnusedVariable class Creating_container { [Test] public void Example() { var container = new Container(); // start using the container.. } } ``` -------------------------------- ### Example Usage of Async Interceptor with DryIoc Source: https://github.com/dadhi/dryioc/blob/master/docs/DryIoc.Docs/Interception.md Demonstrates registering an async interceptor and applying it to a service. Verifies that the interceptor is invoked correctly. ```cs public class Register_and_use_async_interceptor { public interface IFoo { Task HeyAsync(string name); } public class Foo : IFoo { public async Task HeyAsync(string name) { await Task.Delay(30); return $"Hey {name} async!"; } } public class SomeAsyncInterceptor : ProcessingAsyncInterceptor { public List Interceptions = new List(); protected override string StartingInvocation(IInvocation invocation) { var method = invocation.GetConcreteMethod().Name; var arg = invocation.Arguments[0]; return $"intercept BEFORE async method call of `{method}` with argument `{arg}`; "; } protected override void CompletedInvocation(IInvocation invocation, string state) { var method = invocation.GetConcreteMethod().Name; var res = invocation.ReturnValue; Interceptions.Add(state + "intercept AFTER async method call of `{methodName}` with the result `{res}`;"); } } [Test] public async Task Example() { var container = new Container(); container.Register(); container.Register(Reuse.Singleton); container.InterceptAsync(); var foo = container.Resolve(); var result = await foo.HeyAsync("NyanCat"); var interceptor = container.Resolve(); Assert.AreEqual(1, interceptor.Interceptions.Count); } } ``` -------------------------------- ### Preventing Disposal Tracking with Setup Option Source: https://github.com/dadhi/dryioc/blob/master/docs/DryIoc.Docs/ReuseAndScopes.md Use `preventDisposal: true` in the `Setup.With` options to explicitly prevent a registered service from being tracked for disposal by the container. ```csharp container.Register(setup: Setup.With(preventDisposal: true)); ``` -------------------------------- ### Register Service with Instance Factory Method Source: https://github.com/dadhi/dryioc/blob/master/docs/DryIoc.Docs/SelectConstructorOrFactoryMethod.md Register a service using an instance factory method, allowing for chained factory creation. This example demonstrates creating an `IFoo` using a `FooFactory` instance. ```cs public class Register_with_instance_factory_method { [Test] public void Example() { var c = new Container(); c.Register(Reuse.Singleton); c.Register(); c.Register(); c.Register(made: Made.Of(r => ServiceInfo.Of(), f => f.CreateFoo(Arg.Of()))); Assert.IsNotNull(c.Resolve()); } public interface IFooFactory { IFoo CreateFoo(Repo repo); } public class FooFactory : IFooFactory { public FooFactory(IDependency dep) { } public IFoo CreateFoo(Repo repo) { var foo = new FooBar(); repo.Add(foo); return foo; } } public interface IFoo { } public class FooBar : IFoo { } public class Repo { public void Add(IFoo foo) { } } } ``` -------------------------------- ### Define Services and Clients in C# Source: https://github.com/dadhi/dryioc/blob/master/docs/DryIoc.Docs/Home.md Defines interfaces and their implementations for services and clients, setting up the basic structure for dependency injection examples. ```csharp namespace Dryioc.Docs; using Dryioc; using NUnit.Framework; // ReSharper disable UnusedVariable public interface IService { } public class SomeService : IService { } // A client consuming the `IService` dependency public interface IClient { IService Service { get; } } public class SomeClient : IClient { public IService Service { get; } public SomeClient(IService service) { Service = service; } } ``` -------------------------------- ### Solution: Using Parameters.Of to Match Parameter Names to Service Keys Source: https://github.com/dadhi/dryioc/blob/master/docs/DryIoc.Docs/SpecifyDependencyAndPrimitiveValues.md Illustrates how to use `Parameters.Of` to explicitly map constructor parameter names to their corresponding service keys, resolving the ambiguity from the previous example. This ensures DryIoc selects the correct implementation. ```csharp [Test] public void Solution() { var c = new Container(); c.Register(serviceKey: "a"); c.Register(serviceKey: "b"); c.Register(made: Made.Of(parameters: Parameters.Of .Name("a", serviceKey: "a") .Name("b", serviceKey: "b"))); var example = c.Resolve(); Assert.IsNotNull(example); } ``` -------------------------------- ### IDictionary Example: Services with String and Int Keys Source: https://github.com/dadhi/dryioc/blob/master/docs/DryIoc.Docs/Wrappers.md Illustrates resolving IDictionary and IDictionary to access services registered with specific string and integer keys. It also shows how to resolve all services using IDictionary. ```cs public class Dictionary_of_services_with_their_keys { [Test] public void Example() { var container = new Container(); container.Register(serviceKey: "A"); container.Register(); // no key container.Register(serviceKey: "C"); container.Register(serviceKey: 42); container.Register(); // inject 2 services with string keys into consumer constructor var c = container.Resolve(); Assert.AreEqual(2, c.Services.Count); Assert.IsInstanceOf(c.Services["A"]); Assert.IsInstanceOf(c.Services["C"]); // resolve single int service as dictionary var i = container.Resolve>(); Assert.AreEqual(1, i.Count); Assert.IsInstanceOf(i[42]); // resolve all services as dictionary with object key, including the B without key var all = container.Resolve>(); Assert.AreEqual(4, all.Count); Assert.IsInstanceOf(all[DefaultKey.Value]); } interface I { } class A : I { } class B : I { } class C : I { } class D : I { } class Consumer { public readonly IDictionary Services; public Consumer(IDictionary services) => Services = services; } } ``` -------------------------------- ### Registering a Generic User-Defined Wrapper Source: https://github.com/dadhi/dryioc/blob/master/docs/DryIoc.Docs/Wrappers.md Demonstrates how to register a generic user-defined wrapper using Setup.Wrapper and verifies its registration. ```cs container.Register(typeof(MenuItem<>), setup: Setup.Wrapper); Assert.IsTrue(container.IsRegistered(typeof(MenuItem<>), factoryType: FactoryType.Wrapper)); ``` -------------------------------- ### Build and Test Solution Source: https://github.com/dadhi/dryioc/blob/master/CONTRIBUTING.md Run this batch file from the root folder to build all projects in Release configuration, run unit tests, and generate documentation. Ensure there are no build errors or failing tests before submitting a Pull Request. ```batch b.bat ``` -------------------------------- ### Define Interfaces and Classes for Mocking Source: https://github.com/dadhi/dryioc/blob/master/docs/DryIoc.Docs/UsingInTestsWithMockingLibrary.md Defines the interfaces and consumer classes that will be used in the mocking examples. ```cs public interface INotImplementedService { } public class SomeConsumer { public INotImplementedService Service { get; } public SomeConsumer(INotImplementedService service) { Service = service; } } ``` -------------------------------- ### Various Open-Generic Registration Options Source: https://github.com/dadhi/dryioc/blob/master/docs/DryIoc.Docs/OpenGenerics.md Illustrates different ways to register open-generic services, including specifying reuse, handling already registered services, using decorators, and applying service keys. ```csharp public class Open_generic_registrations { [Test] public void Example() { var container = new Container(); container.Register(typeof(Command<>)); container.Register(typeof(Command<>), Reuse.Singleton); container.Register(typeof(ICommand<>), typeof(Command<>), ifAlreadyRegistered: IfAlreadyRegistered.AppendNewImplementation, serviceKey: "blah"); container.Register(typeof(ICommand<>), typeof(LoggingCommand<>), setup: Setup.Decorator); // etc. } interface ICommand { } class Command : ICommand { } class LoggingCommand : ICommand { } } ``` -------------------------------- ### Get Service Registrations in DryIoc Source: https://github.com/dadhi/dryioc/blob/master/docs/DryIoc.Docs/FaqAutofacMigration.md Retrieves all service registrations from the container. Use this to inspect registration details. ```cs IEnumerable registrations = container.GetServiceRegistrations(); foreach (var r in registrations) { /*...*/ } ``` -------------------------------- ### Solution: Applying Parameter Matching Rules at Container Level Source: https://github.com/dadhi/dryioc/blob/master/docs/DryIoc.Docs/SpecifyDependencyAndPrimitiveValues.md Explains how to apply parameter matching rules globally at the container level using `rules.With(parameters: ...)`. This approach sets default parameter resolution strategies for all registrations within the container, including specific handling for `ExampleClass`. ```csharp [Test] public void Solution_with_the_rule_applied_on_container_level() { var c = new Container(rules => rules.With(parameters: Parameters.Of.Details( (req, parInfo) => req.ServiceType == typeof(ExampleClass) ? ServiceDetails.Of(serviceKey: parInfo.Name) : null))); c.Register(serviceKey: "a"); c.Register(serviceKey: "b"); c.Register(); Assert.IsNotNull(c.Resolve()); } } ``` -------------------------------- ### ResolveMany with Dynamic Registration vs. Unknown Service Resolvers Source: https://github.com/dadhi/dryioc/blob/master/docs/DryIoc.Docs/RulesAndDefaultConventions.md Illustrates how `ResolveMany` behaves with `WithDynamicRegistration` and `UnknownServiceResolvers`. The first example shows `ResolveMany` failing when using `UnknownServiceResolvers` with a parent container, resulting in zero resolved services. The second example demonstrates `ResolveMany` successfully resolving multiple services when `WithDynamicRegistrations` is configured with a custom `DynamicRegistrationProvider` that correctly translates service keys. ```cs public class ResolveMany_does_not_work_WithUnknownResolvers { [Test]public void Example_not_working() { var parent = new Container(); parent.Register(); parent.Register(); var child = new Container(Rules.Default.WithUnknownServiceResolvers(req => DelegateFactory.Of(_ => parent.Resolve(req.ServiceType)))); // does not work var actual = child.ResolveMany(); // the result count is 0! Assert.AreEqual(0, actual.Count()); } [Test]public void Example_working() { var parent = new Container(); parent.Register(); parent.Register(); Rules.DynamicRegistrationProvider dynamicRegistration = (serviceType, serviceKey) => new[] { new DynamicRegistration(DelegateFactory.Of(_ => parent.Resolve(serviceType, serviceKey is DefaultDynamicKey dk ? DefaultKey.Of(dk.RegistrationOrder) : null))) }; // we need the double dynamic registrations here because we have a two default services and // the service key translation is the key ;-) to distinguish between the services var child = new Container(Rules.Default.WithDynamicRegistrations( DynamicRegistrationFlags.AsFallback | DynamicRegistrationFlags.Service, dynamicRegistration, dynamicRegistration)); // works var actual = child.ResolveMany().ToArray(); // 2 services are resolved Assert.AreEqual(2, actual.Length); CollectionAssert.AreEquivalent(new[] { typeof(Service1), typeof(Service2) }, actual.Select(x => x.GetType())); } interface IService { } class Service1: IService { } class Service2: IService { } } ``` -------------------------------- ### Solution: Matching All Registration Parameters by Name Source: https://github.com/dadhi/dryioc/blob/master/docs/DryIoc.Docs/SpecifyDependencyAndPrimitiveValues.md Demonstrates a more generic approach to matching parameter names to service keys using `Parameters.Of.Details`. This method dynamically determines the service key based on the parameter's name, but can be fragile if non-keyed parameters are added later. ```csharp [Test] public void Solution_matching_all_registration_parameters() { var c = new Container(); c.Register(serviceKey: "a"); c.Register(serviceKey: "b"); c.Register(made: Parameters.Of.Details( (req, parInfo) => ServiceDetails.Of(serviceKey: parInfo.Name))); Assert.IsNotNull(c.Resolve()); } ``` -------------------------------- ### Registering a Non-Generic User-Defined Wrapper Source: https://github.com/dadhi/dryioc/blob/master/docs/DryIoc.Docs/Wrappers.md Shows how to register a non-generic user-defined wrapper for a specific service type using Setup.Wrapper. ```cs container.Register(setup: Setup.Wrapper); Assert.IsTrue(container.IsRegistered(typeof(MyWrapper), factoryType: FactoryType.Wrapper)); ``` -------------------------------- ### Resolving Complex Wrapper Combinations Source: https://github.com/dadhi/dryioc/blob/master/docs/DryIoc.Docs/Wrappers.md Provides examples of resolving collections with various combinations of KeyValuePairs, Metadata, Lazy, and Func delegates. ```cs container.Resolve, MyMetadata>>>>(); ``` ```cs container.Resolve[]>(); ``` ```cs container.Resolve, object>>(); ``` -------------------------------- ### Full Made Specification with Reflection Source: https://github.com/dadhi/dryioc/blob/master/docs/DryIoc.Docs/SpecifyDependencyAndPrimitiveValues.md Demonstrates using reflection to specify the constructor, parameters, and properties/fields for service creation. Use when the constructor or parameters cannot be determined at compile time. ```cs public class Full_spec_with_reflection { [Test] public void Example() { var container = new Container(); container.Register(made: Made.Of( r => FactoryMethod.Of(typeof(Foo).GetConstructorOrNull(args: new[] { typeof(IDependency) })), parameters: Parameters.Of.Type(requiredServiceType: typeof(TestDependency)), propertiesAndFields: PropertiesAndFields.Auto)); } public interface IFoo {} public class Foo : IFoo {} public interface IDependency {} public class TestDependency : IDependency {} } ``` -------------------------------- ### Build Documentation Source: https://github.com/dadhi/dryioc/blob/master/CONTRIBUTING.md Run this batch file from the root folder to build the documentation after editing the .cs files. This process converts C# documentation files into markdown (.md) files. ```batch build_the_docs.bat ``` -------------------------------- ### Registering a fixed array of services Source: https://github.com/dadhi/dryioc/blob/master/docs/DryIoc.Docs/Wrappers.md Demonstrates how to register a fixed array of service implementations. The array is created once and does not update with new registrations. ```cs var items = new B(new A[] { new Impl1(), new Impl2(), new Impl3() }); ``` -------------------------------- ### Registering a Placeholder Service Source: https://github.com/dadhi/dryioc/blob/master/docs/DryIoc.Docs/RegisterResolve.md Demonstrates how to register a placeholder for a service and later replace it with a concrete implementation. Throws an exception if resolution is attempted before an implementation is registered. ```cs public class Register_placeholder { [Test] public void Example() { var container = new Container(); container.RegisterPlaceholder(); var getService = container.Resolve>(); // Throws because service is just a placeholder and does not have implementation registered yet IService service; Assert.Throws(() => service = getService()); // Replace placeholder with a real implementation container.Register(ifAlreadyRegistered: IfAlreadyRegistered.Replace); service = getService(); Assert.IsInstanceOf(service); } interface IService { } class Foo : IService { } } ``` -------------------------------- ### Composite Pattern Example Structure Source: https://github.com/dadhi/dryioc/blob/master/docs/DryIoc.Docs/Wrappers.md Defines the basic structure of classes involved in the Composite pattern, where a composite service depends on a collection of other services of the same type. ```cs class Composite_example { class A1 : A {} class A2 : A {} class Composite : A { public Composite(A[] items) { } } } ``` -------------------------------- ### Register Delegate Resolving Dependencies Source: https://github.com/dadhi/dryioc/blob/master/docs/DryIoc.Docs/RegisterResolve.md Use the IResolverContext to resolve additional dependencies needed for service creation. This example resolves a GreetingsProvider to initialize CheerfulService. ```csharp public class Register_delegate_with_resolved_dependencies { [Test] public void Example() { var container = new Container(); container.RegisterDelegate(_ => new GreetingsProvider { Greetings = "Mya" }); container.RegisterDelegate(resolverContext => new CheerfulService(resolverContext.Resolve())); var x = container.Resolve(); Assert.AreEqual("Mya", ((CheerfulService)x).Greetings); } class GreetingsProvider { public string Greetings { get; set; } } class CheerfulService : IService { public string Greetings => _greetingsProvider.Greetings; public CheerfulService(GreetingsProvider greetingsProvider) { _greetingsProvider = greetingsProvider; } private readonly GreetingsProvider _greetingsProvider; } } ``` -------------------------------- ### C#: ThrowIfDependencyHasShorterReuseLifespan Example Source: https://github.com/dadhi/dryioc/blob/master/docs/DryIoc.Docs/RulesAndDefaultConventions.md Demonstrates the default behavior of ThrowIfDependencyHasShorterReuseLifespan rule, which throws an exception when a dependency with a shorter lifespan is injected into a holder with a longer lifespan. ```csharp public class Throw_if_dependency_has_a_shorter_lifetime { [Test] public void Example() { var container = new Container(); // enabled by default container.Register(Reuse.Singleton); container.Register(Reuse.InCurrentScope); using (var scope = container.OpenScope()) { var ex = Assert.Throws(() => scope.Resolve()); Assert.AreEqual(Error.NameOf(Error.DependencyHasShorterReuseLifespan), ex.ErrorName); } } class A { public A(B b) { } } class B { } } ``` -------------------------------- ### Registering and Resolving a Service with Dependency Source: https://github.com/dadhi/dryioc/blob/master/docs/DryIoc.Docs/SpecifyDependencyAndPrimitiveValues.md Demonstrates basic registration of a service and its dependency, followed by resolving the service. The container uses the parameter type of the constructor to find the registered service. ```csharp namespace DryIoc.Docs; using System; using NUnit.Framework; using DryIoc; // ReSharper disable UnusedVariable public class Resolving_with_a_service_type { [Test] public void Example() { var container = new Container(); container.Register(); container.Register(); // elsewhere container.Resolve(); } public interface IDependency {} public class Dependency : IDependency {} public class Foo { public Foo(IDependency dependency) { /*...*/} } } ``` -------------------------------- ### Autofac Owned Instance Example Source: https://github.com/dadhi/dryioc/blob/master/docs/DryIoc.Docs/FaqAutofacMigration.md Demonstrates Autofac's `Owned` for managing scopes and disposing nested dependencies. `InstancePerOwned` is used for scoped registrations. ```cs class SomeService { public SomeService(Dependency d) {} } class SomeClient : IDisposable { // Owned will open scope and provide access for its disposal public SomeClient(Owned owned) { _owned = owned; } // Will dispose scoped dependency and nested dependencies public void Dispose() { _owned.Dispose(); } } // configure: builder.RegisterType().InstancePerOwned(); builder.RegisterType().InstancePerOwned(); builder.RegisterType(); builder.RegisterType(); ``` -------------------------------- ### Registering and Resolving Multiple Keyed Commands Source: https://github.com/dadhi/dryioc/blob/master/docs/DryIoc.Docs/RegisterResolve.md Demonstrates registering different command implementations with specific enum keys and resolving them individually or as an array. Shows how to use ResolveMany with different behaviors. ```csharp public class Multiple_keyed_registrations { internal interface ICommand { } internal class GetCommand : ICommand { } internal class SetCommand : ICommand { } internal class DeleteCommand : ICommand { } enum CommandId { Get, Set, Delete } [Test] public void Example() { var container = new Container(); container.Register(serviceKey: CommandId.Get); container.Register(serviceKey: CommandId.Set); container.Register(serviceKey: CommandId.Delete); // then specify the required key on resolve var setCommand = container.Resolve(serviceKey: CommandId.Set); Assert.IsInstanceOf(setCommand); // get array of all commands, regardless of the key var commands = container.Resolve(); Assert.AreEqual(3, commands.Length); // you may select a specific behavior of ResolveMany: var commands2 = (ICommand[])container.ResolveMany(behavior: ResolveManyBehavior.AsFixedArray); Assert.AreEqual(3, commands2.Length); } } ``` -------------------------------- ### Emulating Func for Service Resolution by Key Source: https://github.com/dadhi/dryioc/blob/master/docs/DryIoc.Docs/Wrappers.md This example demonstrates how to emulate the Func pattern in DryIoc, where the string argument acts as a service key. It registers services with string keys and then registers a delegate to resolve the correct service based on the provided key. ```cs public class Func_with_single_argument_to_resolve_service_by_key { [Test] public void Example() { var container = new Container(); container.Register(serviceKey: "A"); container.Register(serviceKey: "B"); container.Register(); // The magic is not: // DryIoc will inject the IDictionary wrapper of services by key and a string key passed as function argument container.RegisterDelegate, string, IService>((services, key) => services[key]); var getConsumer = container.Resolve>(); Assert.IsInstanceOf(getConsumer("A").Service); Assert.IsInstanceOf(getConsumer("B").Service); } interface IService {} class ServiceA : IService {} class ServiceB : IService {} class Consumer { public readonly IService Service; public Consumer(IService service) => Service = service; } } ``` -------------------------------- ### Detecting Captive Dependency with Validate Source: https://github.com/dadhi/dryioc/blob/master/docs/DryIoc.Docs/ErrorDetectionAndResolution.md Use `container.Validate()` to check for captive dependencies. This example specifically targets a Scoped dependency injected into a Singleton, which is reported as an error. ```cs public class Validate_CaptiveDependency_example { [Test] public void Scoped_in_a_Singleton_should_be_reported_by_Validate() { var container = new Container(); container.Register(Reuse.Scoped); container.Register(Reuse.Singleton); container.Register(Reuse.Scoped); // here is the problem! var errors = container.Validate(ServiceInfo.Of()); Assert.AreEqual(1, errors.Length); var error = errors[0].Value; Assert.AreEqual(Error.NameOf(Error.DependencyHasShorterReuseLifespan), error.ErrorName); /* Exception message: code: Error.DependencyHasShorterReuseLifespan; message: Dependency Buz as parameter "buz" (IsSingletonOrDependencyOfSingleton) with reuse Scoped {Lifespan=100} has a shorter lifespan than its parent's Singleton Bar as parameter "bar" FactoryID=145 (IsSingletonOrDependencyOfSingleton) in resolution root Scoped Foo FactoryID=144 from container without scope with Rules with {UsedForValidation} and without {ImplicitCheckForReuseMatchingScope, EagerCachingSingletonForFasterAccess} with DependencyCountInLambdaToSplitBigObjectGraph=2147483647 If you know what you're doing you may disable this error with the rule `new Container(rules => rules.WithoutThrowIfDependencyHasShorterReuseLifespan())`. */ } public class Foo { public Foo(Bar bar) {} } public class Bar { public Bar(Buz buz) {} } public class Buz { } } ``` -------------------------------- ### Registering Disposable Transient in DryIoc Source: https://github.com/dadhi/dryioc/blob/master/docs/DryIoc.Docs/FaqAutofacMigration.md Use `allowDisposableTransient` setup option or `WithoutThrowOnRegisteringDisposableTransient()` container rule to allow registering disposable transients, similar to Autofac's `ExternallyOwned()`. ```cs container.Register(setup: Setup.With(allowDisposableTransient: true)); ``` ```cs container.Register(rules: Rules.WithoutThrowOnRegisteringDisposableTransient()); ``` -------------------------------- ### Registering and Resolving Meta Source: https://github.com/dadhi/dryioc/blob/master/docs/DryIoc.Docs/Wrappers.md Demonstrates registering a service with string metadata and resolving it using both Meta and Tuple. Note that Tuple is functionally equivalent to Meta in this context. ```cs public class Providing_metadata { [Test] public void Example() { var container = new Container(); container.Register(setup: Setup.With(metadataOrFuncOfMetadata: "XYZ")); var a1 = container.Resolve>(); var a2 = container.Resolve>(); // is the same thing Assert.AreEqual("XYZ", a1.Metadata); Assert.AreEqual("XYZ", a2.Item2); } } ``` -------------------------------- ### LazyEnumerable Example: Resolving Up-to-date Services Source: https://github.com/dadhi/dryioc/blob/master/docs/DryIoc.Docs/Wrappers.md Demonstrates how LazyEnumerable resolves services dynamically, reflecting changes in the container after initial resolution. It shows that the collection is not materialized until enumerated. ```cs public class LazyEnumerable_example { [Test] public void Example() { var container = new Container(); container.Register(); // At that point, not even `A1` is resolved var items = container.Resolve>(); // `A1` is resolved var materializedItems = items.ToArray(); Assert.IsInstanceOf(materializedItems.Single()); // Adding a new service container.Register(); items = container.Resolve>(); materializedItems = items.ToArray(); // Now result collection contains `A1` and `A2` Assert.AreEqual(2, materializedItems.Length); } class A { } class A1 : A { } class A2 : A { } } ``` -------------------------------- ### Detecting Reuse Lifespan Mismatch in DryIoc Source: https://github.com/dadhi/dryioc/blob/master/docs/DryIoc.Docs/ReuseAndScopes.md This example demonstrates how DryIoc throws an exception when a Scoped dependency is used within a Singleton service, indicating a lifespan mismatch. ```cs public class Reuse_lifespan_mismatch_detection { [Test] public void Example() { var container = new Container(); container.Register(Reuse.Singleton); container.Register(Reuse.Scoped); using (var scope = container.OpenScope()) { // Throws an exception with captive dependency detected: // dependency Scoped lifespan is less than parent Singleton lifespan Assert.Throws(() => scope.Resolve()); } } class Mercedes { public Mercedes(Wheels wheels) { } } class Wheels { } } ``` -------------------------------- ### Using enum service key with parameter specification Source: https://github.com/dadhi/dryioc/blob/master/docs/DryIoc.Docs/SpecifyDependencyAndPrimitiveValues.md Demonstrates an alternative way to specify service keys for dependencies using the Parameters.Of.Type method, which is less refactoring-friendly than using Arg. ```csharp public class Using_the_enum_service_key_and_parameter_specification { [Test] public void Example() { var container = new Container(); container.Register(serviceKey: SomeKind.In); container.Register(serviceKey: SomeKind.Out); container.Register(made: Parameters.Of.Type(serviceKey: SomeKind.In)); var foo = container.Resolve(); Assert.IsInstanceOf(foo.Dependency); } public enum SomeKind { In, Out } public interface IDependency {} public class XDependency : IDependency {} public class YDependency : IDependency {} public class Foo { public IDependency Dependency; public Foo(IDependency dependency) => Dependency = dependency; } } ``` -------------------------------- ### Nested Decorators Example Source: https://github.com/dadhi/dryioc/blob/master/docs/DryIoc.Docs/Decorators.md Demonstrates how DryIoc handles nested decorators. The order of registration determines the wrapping order, with the last registered decorator wrapping the inner ones. ```cs class S { } class D1 : S { public D1(S s) { } } class D2 : S { public D2(S s) { } } public class Nested_decorators { [Test] public void Example() { var container = new Container(); container.Register(); container.Register(setup: Setup.Decorator); container.Register(setup: Setup.Decorator); var s = container.Resolve(); // s is created as `new D2(new D1(new S()))` Assert.IsInstanceOf(s); // ACTUALLY, you even can see how service is created yourself var expr = container.Resolve(typeof(S)); StringAssert.Contains("new D2(new D1(new S()))", expr.ToString()); } } ``` -------------------------------- ### Customizing Container Rules Source: https://github.com/dadhi/dryioc/blob/master/docs/DryIoc.Docs/CreatingAndDisposingContainer.md Demonstrates how to create new container instances with modified rules using `With..` and `Without..` methods. Use this to alter default container behavior. ```csharp public class Adding_some_rules { [Test] public void Example() { var container1 = new Container( Rules.Default.With(FactoryMethod.ConstructorWithResolvableArguments)); var container2 = new Container( Rules.Default.WithoutThrowIfDependencyHasShorterReuseLifespan()); } } ``` -------------------------------- ### Registering an Open-Generic Service Source: https://github.com/dadhi/dryioc/blob/master/docs/DryIoc.Docs/OpenGenerics.md Demonstrates the basic registration of an open-generic service type with its implementation. Requires using `typeof` for generic types. ```csharp namespace DryIoc.Docs; using System; using System.Linq; using DryIoc; using NUnit.Framework; // ReSharper disable UnusedTypeParameter public class Register_open_generic { [Test] public void Example() { var container = new Container(); container.Register(typeof(ICommand<>), typeof(DoSomethingCommand<>)); var cmd = container.Resolve>(); Assert.IsInstanceOf>(cmd); } interface ICommand { } class DoSomethingCommand : ICommand { } struct MyData { } } ``` -------------------------------- ### Full SignalR Integration with WithSignalR Source: https://github.com/dadhi/dryioc/blob/master/docs/DryIoc.Docs/Extensions/SignalR.md Use the `WithSignalR` extension method for a complete DryIoc and SignalR setup. This registers `DryIocHubActivator`, hubs from specified assemblies, and sets `GlobalHost.DependencyResolver` to `DryIocDependencyResolver`. ```csharp var hubAssemblies = new[] { Assembly.GetExecutingAssembly() }; container = new Container().WithSignalR(hubAssemblies); RouteTable.Routes.MapHubs(); ``` -------------------------------- ### Resolving Services as KeyValuePair Wrappers Source: https://github.com/dadhi/dryioc/blob/master/docs/DryIoc.Docs/RegisterResolve.md Demonstrates resolving services registered with different keys (including default and string keys) as KeyValuePair wrappers. Shows how to filter by key type. ```csharp public class Resolving_service_with_key_as_KeyValuePair { interface I { } class X : I { } class Y : I { } class Z : I { } [Test] public void Example() { var container = new Container(); container.Register(); container.Register(); container.Register(serviceKey: "z"); // use an `object` key to get all of the registrations var items = container.Resolve[]>(); // the keys of resolved items CollectionAssert.AreEqual( new object[] { DefaultKey.Of(0), DefaultKey.Of(1), "z" }, items.Select(x => x.Key)); // you may get only services with default keys var defaultItems = container.Resolve[]>(); Assert.AreEqual(2, defaultItems.Length); // or the one with string key var z = container.Resolve[]>().Single().Value; Assert.IsInstanceOf(z); } } ``` -------------------------------- ### Configure UseParentReuse for Dependencies Source: https://github.com/dadhi/dryioc/blob/master/docs/DryIoc.Docs/ReuseAndScopes.md Demonstrates how to enable `useParentReuse` for a dependency. This allows a dependency to inherit the reuse of its parent or ancestor service. If the parent is Transient, it searches for the first non-Transient ancestor. ```csharp public class Use_parent_reuse { [Test] public void Example() { var container = new Container(); container.Register(Reuse.Singleton); container.Register(); container.Register(setup: Setup.With(useParentReuse: true)); // same Mercedes with the same Wheels var m1 = container.Resolve(); var m2 = container.Resolve(); Assert.AreSame(m1.Wheels, m2.Wheels); // different Dodges with the different Wheels var d1 = container.Resolve(); var d2 = container.Resolve(); Assert.AreNotSame(d1.Wheels, d2.Wheels); } class Mercedes { public Wheels Wheels { get; } public Mercedes(Wheels wheels) { Wheels = wheels; } } class Dodge { public Wheels Wheels { get; } public Dodge(Wheels wheels) { Wheels = wheels; } } private class Wheels { } } ```