{"id":13629511,"url":"https://github.com/YairHalberstadt/stronginject","last_synced_at":"2025-04-17T09:34:27.608Z","repository":{"id":37358395,"uuid":"277733754","full_name":"YairHalberstadt/stronginject","owner":"YairHalberstadt","description":"compile time dependency injection for .NET","archived":false,"fork":false,"pushed_at":"2022-07-08T19:22:49.000Z","size":1418,"stargazers_count":840,"open_issues_count":19,"forks_count":24,"subscribers_count":28,"default_branch":"main","last_synced_at":"2024-05-22T04:33:46.700Z","etag":null,"topics":["csharp","csharp-sourcegenerator","di","dotnet","hacktoberfest","ioc","source-generators"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/YairHalberstadt.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-07-07T06:18:39.000Z","updated_at":"2024-05-15T10:32:57.000Z","dependencies_parsed_at":"2022-09-12T23:51:55.598Z","dependency_job_id":null,"html_url":"https://github.com/YairHalberstadt/stronginject","commit_stats":null,"previous_names":[],"tags_count":19,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/YairHalberstadt%2Fstronginject","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/YairHalberstadt%2Fstronginject/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/YairHalberstadt%2Fstronginject/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/YairHalberstadt%2Fstronginject/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/YairHalberstadt","download_url":"https://codeload.github.com/YairHalberstadt/stronginject/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":223286107,"owners_count":17119985,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["csharp","csharp-sourcegenerator","di","dotnet","hacktoberfest","ioc","source-generators"],"created_at":"2024-08-01T22:01:12.470Z","updated_at":"2024-11-08T20:31:06.825Z","avatar_url":"https://github.com/YairHalberstadt.png","language":"C#","funding_links":[],"categories":["Contributors Welcome for those","csharp","Source Generators","Compile time dependency injection","hacktoberfest","C# #"],"sub_categories":["1. [ThisAssembly](https://ignatandrei.github.io/RSCG_Examples/v2/docs/ThisAssembly) , in the [EnhancementProject](https://ignatandrei.github.io/RSCG_Examples/v2/docs/rscg-examples#enhancementproject) category","Dependency Injection (IoC Container)"],"readme":"![](https://github.com/yairhalberstadt/stronginject/workflows/.NET%20Core/badge.svg)\n[![Join the chat at https://gitter.im/stronginject/community](https://badges.gitter.im/stronginject/community.svg)](https://gitter.im/stronginject/community?utm_source=badge\u0026utm_medium=badge\u0026utm_campaign=pr-badge\u0026utm_content=badge)\n[![NuGet (with prereleases)](https://img.shields.io/nuget/vpre/StrongInject)](https://www.nuget.org/packages/StrongInject)\n\n![StrongInject](resources/logo-horizontal.png)\n\n**Compile Time Dependency Injection For C#**\n\nLogo kindly contributed by [@onelioubov](https://github.com/onelioubov) and [@khalidabuhakmeh](https://github.com/khalidabuhakmeh)\n\n\u003c!-- START doctoc generated TOC please keep comment here to allow auto update --\u003e\n\u003c!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --\u003e\n## Table Of Contents\n\n- [Aims](#aims)\n- [Requirements](#requirements)\n- [NuGet](#nuget)\n- [How It Works](#how-it-works)\n- [Usage](#usage)\n  - [Sample Projects](#sample-projects)\n      - [ASP.NET Core/Microsoft.Extensions.DependencyInjection](#aspnet-coremicrosoftextensionsdependencyinjection)\n      - [Console Application](#console-application)\n      - [Xamarin Application](#xamarin-application)\n      - [WPF Application](#wpf-application)\n    - [Real World Projects Using StrongInject](#real-world-projects-using-stronginject)\n  - [Declaring a container](#declaring-a-container)\n  - [Using a container](#using-a-container)\n  - [Registration](#registration)\n    - [Basics](#basics)\n    - [Scope](#scope)\n    - [Modules](#modules)\n    - [Instance fields and properties](#instance-fields-and-properties)\n    - [Factories](#factories)\n    - [Generic Factory Methods](#generic-factory-methods)\n      - [Factory Of Methods](#factory-of-methods)\n    - [Decorators](#decorators)\n    - [Providing registrations at runtime or integrating with other IOC containers](#providing-registrations-at-runtime-or-integrating-with-other-ioc-containers)\n    - [How StrongInject picks which registration to use](#how-stronginject-picks-which-registration-to-use)\n  - [Delegate Support](#delegate-support)\n  - [`Owned\u003cT\u003e` support](#ownedt-support)\n  - [Post Constructor Initialization](#post-constructor-initialization)\n  - [Async Support](#async-support)\n    - [Parallel Resolution](#parallel-resolution)\n  - [Resolving all instances of a type](#resolving-all-instances-of-a-type)\n  - [Optional Parameters](#optional-parameters)\n  - [Disposal](#disposal)\n  - [Thread Safety](#thread-safety)\n  - [Inbuilt Modules](#inbuilt-modules)\n- [Product Roadmap](#product-roadmap)\n- [Contributing](#contributing)\n- [Need Help?](#need-help)\n\n\u003c!-- END doctoc generated TOC please keep comment here to allow auto update --\u003e\n\n## Aims\n\n1. **Compile time checked dependency injection.** If the type you're resolving isn't registered you get an error at compile time, not runtime.\n2. **Fast.** There's no dictionary lookups, no runtime code generation. Just the fastest code it's possible to generate to resolve your type.\n3. **Encourage best practices.** You can't use the container as a service locator. You can't forget to dispose the resolved types.\n4. **No reflection or runtime code generation.** Instead StrongInject uses roslyn Source Generators, meaning it's fast, and works well on UWP/IOS too. This also means it's linker friendly - see https://devblogs.microsoft.com/dotnet/app-trimming-in-net-5/.\n5. **Async support.** StrongInject fully supports async initialization and disposal, a feature sorely lacking in many IOC containers.\n\n## Requirements\n\n[Visual Studio 16.8](https://visualstudio.microsoft.com/vs) or greater\n\n[.NET 5.0.102 SDK](https://dotnet.microsoft.com/download/dotnet/5.0) or greater\n\n## NuGet\n\nhttps://www.nuget.org/packages/StrongInject/\n\n`\u003cPackageReference Include=\"StrongInject\" Version=\"1.*.*\" /\u003e`\n\n## How It Works\n\nTo use StrongInject, you first need to tell StrongInject the top-level services you would like to resolve. You do this by adding a new class implementing `IContainer\u003cT\u003e`. This will be your container. If you want to resolve multiple top-level services, then you can implement `IContainer\u003cT\u003e` multiple times on one container, or create multiple containers. StrongInject will then check at compile time that you've registered everything you need with the container to enable it to resolve all the top-level services. If you haven't, the compilation will fail with an error explaining what's gone wrong.\n\nFor example, if you want to resolve `MyApp` you might try doing this:\n\n```csharp\nusing StrongInject;\n\npublic class MyService {}\npublic class MyApp { public MyApp(MyService myService) {} }\n\n[Register(typeof(MyApp))]\npublic partial class MyContainer : IContainer\u003cMyApp\u003e {}\n```\n\nWhen you try compiling, it will fail with the following error: `SI0102: Error while resolving dependencies for 'MyApp': We have no source for instance of type 'MyService'`.\n\nNow you fix it by adding a registration for `MyService`:\n\n```csharp\nusing StrongInject;\n\npublic class MyService {}\npublic class MyApp { public MyApp(MyService myService) {} }\n\n[Register(typeof(MyApp))]\n[Register(typeof(MyService))]\npublic partial class MyContainer : IContainer\u003cMyApp\u003e {}\n```\n\nAnd this time when you compile, it will succeed and generate all the code needed to resolve an instance of `MyApp` at compile time.\n\nWhat do I mean by a top-level service?\n\nWhen using an IOC container, sometimes you request an instance from the container directly. These are top-level services. Most of the time the container resolves something though, you never ask for it explicitly - instead it's needed as a dependency for something else, which may itself be a dependency or a top-level service etc.\n\nIdeally you want IOC containers to be non invasive - this means you write all your code as if there was no container, and then just use the container once to bootstrap your code. When writing code like this there should only ever be one top-level service. Sometimes this is not possible - for example when integrating with ASP.NET Core your controllers will usually need to be top-level services, but you should always try to minimize the number of top-level services where possible.\n\nThe next section will go into more detail about exactly how to register stuff with containers, and how to use them.\n\n## Usage\n\nThe [wiki](https://github.com/YairHalberstadt/stronginject/wiki) is currently a work in progress. It aims to give a more thorough formal overview of everything in StrongInject, whereas this section of the readme gives a briefer overview relying heavily on examples. I would read through this first, then check out the wiki if you have any questions.\n\n### Sample Projects\n\nCheck out these sample projects to help you get started:\n\n##### [ASP.NET Core/Microsoft.Extensions.DependencyInjection](https://github.com/YairHalberstadt/stronginject/tree/main/Samples/AspNetCore)\n##### [Console Application](https://github.com/YairHalberstadt/stronginject/tree/main/Samples/Console)\n##### [Xamarin Application](https://github.com/YairHalberstadt/stronginject/tree/main/Samples/Xamarin)\n##### [WPF Application](https://github.com/YairHalberstadt/stronginject/tree/main/Samples/Wpf)\n\n#### Real World Projects Using StrongInject\n\n- [FluentLang](https://github.com/YairHalberstadt/fluentlang/blob/master/source/flc/DependencyInjection/FlcContainer.cs)\n\n### Declaring a container\nTo create a container for a specific type, declare your a partial class and implement `StrongInject.IContainer\u003cT\u003e`:\n\n```csharp\nusing StrongInject;\n\npublic class A {}\n\n[Register(typeof(A))]\npublic partial class Container : IContainer\u003cA\u003e {}\n```\n\nIf it's possible to resolve the type parameter StrongInject will generate the implementation of IContainer for you. Else it will produce an error diagnostic.\n\nYou can implement `IContainer\u003cT\u003e` for different values of `T`. They will all share SingleInstance dependencies.\n\n```csharp\nusing StrongInject;\n\npublic class A {}\npublic class B {}\n\n[Register(typeof(A))]\n[Register(typeof(B))]\npublic partial class Container : IContainer\u003cA\u003e, IContainer\u003cB\u003e {}\n```\n\n### Using a container\n\nThere are two ways to use a container - using the `Run` methods or the `Resolve` methods.\n\nEither way you'll find it easier if you use the extension methods defined in `StrongInject.ContainerExtensions` rather than those defined directly on the container, so make sure you're `using StrongInject;`\n\nThe `Run` method on `IContainer\u003cT\u003e` takes a `Func\u003cT, TResult\u003e`. It resolves an instance of `T`, calls the func, disposes of any dependencies which require disposal, and then returns the result of the func. This ensures that you can't forget to dispose any dependencies, but you must make sure not to leak those objects out of the delegate. There are also overloads that allow you to pass in a void returning lambda.\n\n```csharp\npublic class Program\n{\n  public static void Main()\n  {\n    System.Console.WriteLine(new Container().Run(x =\u003e x.ToString()));\n  }\n}\n```\n\nIn some cases this isn't flexible enough, for example if you want to use StrongInject from another IOC container, or you need more fine grained control over the lifetime of `T`.\n\nFor these cases you can call the `Resolve` method. This returns an `Owned\u003cT\u003e` which is essentially a disposable wrapper over `T`. Make sure you call `Owned\u003cT\u003e.Dispose` once you're done using `Owned\u003cT\u003e.Value`.\n\n```csharp\npublic class Program\n{\n  public static void Main()\n  {\n    using var ownedOfA = new Container().Resolve();\n    var a = ownedOfA.Value;\n    System.Console.WriteLine(a.ToString());\n  }\n}\n```\n\n### Registration\n\n#### Basics\n\nAs you saw above, you can register a type with a container using the `RegisterAttribute`:\n\n```csharp\nusing StrongInject;\n\npublic class A {}\npublic class B {}\n\n[Register(typeof(A))]\n[Register(typeof(B))]\npublic partial class Container : IContainer\u003cA\u003e, IContainer\u003cB\u003e {}\n```\n\nAll the dependencies of the container type parameter must be registered or you will get a compile time error.\n\nBy default `[Register(typeof(A))]` will register a type `A` as itself. You can however register a type as any base type or implemented interface:\n\n```csharp\nusing StrongInject;\n\npublic class BaseBase {}\npublic interface IBase {}\npublic class Base : BaseBase, IBase {}\npublic interface IA {}\npublic class A : Base, IA {}\n\n[Register(typeof(A), typeof(IA), typeof(IBase), typeof(BaseBase))]\npublic partial class Container : IContainer\u003cBaseBase\u003e {}\n```\n\nIf you do so, you will have to explicitly also register it as itself if that is desired: `[Register(typeof(A), typeof(A), typeof(IA), typeof(IBase), typeof(BaseBase))]`\n\nIf you're on C# preview language version a type, you can use the generic versions of the attribute: `[Register\u003cA\u003e]` and `[Register\u003cA, IA\u003e]`.\n\nIf there is a single public non-parameterless constructor, StrongInject will use that to construct the type. If there is no public non-parameterless constructor StrongInject will use the parameterless constructor if it exists and is public. Else it will report an error.\n\nYou can register generic types as well:\n\n```csharp\npublic class A\u003cT\u003e {}\npublic interface IB\u003cT1, T2\u003e {}\npublic class B\u003cT1, T2\u003e : IB\u003cT1, T2\u003e {}\n\n[Register(typeof(A\u003c\u003e))]\n[Register(typeof(B\u003c,\u003e), typeof(IB\u003c,\u003e))]\npublic partial class Container : IContainer\u003cA\u003cint\u003e\u003e, IContainer\u003cIB\u003cstring, object\u003e\u003e {}\n```\n\n#### Scope\n\nThe scope of a registration determines how often a new instance is created, how long it lives, and who uses it.\n\nIt can be set as the second parameter of a registration:\n\n```csharp\nusing StrongInject;\n\npublic class A {}\npublic interface IB {}\npublic class B : IB {}\n\n[Register(typeof(A), Scope.SingleInstance)]\n[Register(typeof(B), Scope.InstancePerResolution, typeof(IB))]\npublic partial class Container : IContainer\u003cA\u003e, IContainer\u003cIB\u003e {}\n```\n\nThere are currently 3 different scopes:\n\n**Instance Per Resolution**\n\nThis is the default scope.\n\nA single instance is shared between all dependencies created for a single resolution. For example if `A` depends on `B` and `C`, and `B` and `C` both depend on an instance of `D`, then when `A` is resolved `B` and `C` will share the same instance of `D`.\n\nNote every SingleInstance dependency defines a separate resolution, so if `B` and/or `C` are SingleInstance they would not share an instance of `D`.\n\nSimilarly every lambda defines a separate resolution, so if `A` depends on `Func\u003cB\u003e`, then each time `Func\u003cB\u003e` is invoked a fresh instance of both `B` and `D` will be created.\n\n**Instance Per Dependency**\n\nA new instance is created for every usage. For example even if type B appears twice in the constructor of `A`, two different instances will be passed into the constructor.\n\n**SingleInstance**\n\nA single instance will be shared across all dependencies, from any resolution\n\n#### Modules\n\nYou can add registrations to any type, and then import them using the `RegisterModuleAttribute`, or by inheriting from the module. This allows you to create reusable modules of common registrations.\n\n```csharp\nusing StrongInject;\n\npublic class A {}\n\n[Register(typeof(A))]\npublic class Module {}\n\n[RegisterModule(typeof(Module))]\npublic partial class Container : IContainer\u003cA\u003e {}\n```\n\nIf you import multiple modules, and they both register the same type differently, you will get an error when trying to resolve an instance of the type.\n\nThere are two ways to solve this:\n\n1. Register the type directly. This will override the registrations in imported modules.\n2. Exclude the registration from one of the modules when you import it: `[RegisterModule(typeof(Module), exclusionList: new [] { typeof(A) })]`\n\n#### Instance fields and properties\n\nYou can mark a field or a property with the `[Instance]` attribute, to register it as an instance of the field/property type. The field/property will be called for every dependency, but it is bad practice for it to be mutable or expensive, and so this should be irrelevant in practice.\n\n```csharp\nusing StrongInject;\nusing System.Collections.Generic;\n\npublic class A\n{\n    public A(Dictionary\u003cstring, object\u003e configuration){}\n}\n\n[Register(typeof(A))]\npublic partial class Container : IContainer\u003cA\u003e\n{\n    [Instance] Dictionary\u003cstring, object\u003e _configuration;\n    public Container(Dictionary\u003cstring, object\u003e configuration) =\u003e _configuration = configuration;\n}\n```\n\nIf the instance field/property is defined on the container type, it can be private or public, instance or static. However if you want to export the instance as part of a module it must be public and static. If you inherit from the module, you can also access protected instances.\n\n```csharp\nusing StrongInject;\nusing System;\n\npublic class A\n{\n    public A(IEqualityComparer\u003cstring\u003e equalityComparer){}\n}\n\npublic class StringEqualityComparerModule\n{\n    [Instance] public static IEqualityComparer\u003cstring\u003e StringEqualityComparer = StringComparer.CurrentCultureIgnoreCase;\n}\n\n[Register(typeof(A))]\n[RegisterModule(typeof(StringEqualityComparerModule))]\npublic partial class Container : IContainer\u003cA\u003e\n{\n}\n```\n\nIf you want the instance to also be registered as its interfaces or base classes, or to be used as a factory for other types, you can configure all this and more using the `options` parameter. The above example could also have been registered like this:\n\n```csharp\nusing StrongInject;\nusing System;\n\npublic class A\n{\n    public A(IEqualityComparer\u003cstring\u003e equalityComparer){}\n}\n\npublic class StringEqualityComparerModule\n{\n    [Instance(Options.AsImplementedInterfaces)] public static StringComparer StringEqualityComparer = StringComparer.CurrentCultureIgnoreCase;\n}\n\n[Register(typeof(A))]\n[RegisterModule(typeof(StringEqualityComparerModule))]\npublic partial class Container : IContainer\u003cA\u003e\n{\n}\n```\n\n#### Factories\n\nSometimes a type requires more complex construction than just calling the constructor. For example you might want to hard code some parameters, or call a factory method. Some types don't have the correct constructors to be registered directly.\n\nIn such cases you can write a method returning the type you want to construct and mark it with the `[Factory]` attribute.\n\n```csharp\nusing StrongInject;\n\npublic interface IInterface {}\npublic class A : IInterface {}\npublic class B : IInterface {}\n\n[Register(typeof(A))]\n[Register(typeof(B))]\npublic partial class Container : IContainer\u003cIInterface[]\u003e\n{\n    [Factory] private IInterface[] CreateInterfaceArray(A a, B b) =\u003e new IInterface[] { a, b };\n}\n```\n\nYou can set the scope of the factory method (how often it's called), by passing in the scope parameter: `[Factory(Scope.SingleInstance)]`.\n\nIf the factory method is defined on the container type, it can be private or public, instance or static. However if you want to export the factory method as part of a module it must be public and static. If you inherit from the module, you can also access protected factories.\n\n```csharp\nusing StrongInject;\n\npublic interface IInterface {}\npublic class A : IInterface {}\npublic class B : IInterface {}\n\npublic class Module\n{\n    [Factory] public static IInterface[] CreateInterfaceArray(A a, B b) =\u003e new IInterface[] { a, b };\n}\n\n[Register(typeof(A))]\n[Register(typeof(B))]\n[RegisterModule(typeof(Module))]\npublic partial class Container : IContainer\u003cIInterface[]\u003e\n{\n}\n```\n\nIf the factory method returns `Task\u003cT\u003e` or `ValueTask\u003cT\u003e` it will be considered an async registration for `T` (see [below](#async-support)).\n\nIn some cases you want to maintain some state in your factory, or control disposal. For such cases the `IFactory\u003cT\u003e` interface exists.\n\nYou can register a type implementing `IFactory\u003cT\u003e` as a Factory Registration.\nThis will automatically register it as both `IFactory\u003cT\u003e` and `T`. An instance of `T` will be constructed by calling `IFactory\u003cT\u003e.Create()`.\n\n```csharp\nusing StrongInject;\nusing System.Buffers;\n\npublic interface IInterface {}\npublic class A : IInterface {}\npublic class B : IInterface {}\npublic record InterfaceArrayFactory(A A, B B) : IFactory\u003cIInterface[]\u003e\n{\n    public IInterface[] Create()\n    {\n        var array = ArrayPool\u003cIInterface\u003e.Shared.Rent(2);\n        array[0] = A;\n        array[1] = B;\n        return array;\n    }\n    public void Release(IInterface[] instance)\n    {\n        ArrayPool\u003cIInterface\u003e.Shared.Return(instance);\n    }\n}\n\n[Register(typeof(A))]\n[Register(typeof(B))]\n[RegisterFactory(typeof(InterfaceArrayFactory))]\npublic partial class Container : IContainer\u003cIInterface[]\u003e { }\n```\n\nWhilst a factory doesn't have to be a record, doing so significantly shortens the amount of code you have to write.\n\nThe scope of the factory and the factory target is controlled separately. This allows you to e.g. have a singleton factory, but call `CreateAsync` on every resolution:\n\n```csharp\n[RegisterFactory(typeof(InterfaceArrayFactory), scope: Scope.SingleInstance, factoryTargetScope: Scope.InstancePerResolution, typeof(IFactory\u003cIInterface[]\u003e))]\n```\n\nIf a factory implements `IFactory\u003cT\u003e` for multiple `T`s it will be registered as a factory for all of them.\n\n#### Generic Factory Methods\n\nA factory method can be generic. All of the type parameters must be used in the return type. When resolving a type StrongInject will first look for non generic registrations which can resolve that type. If there are none, it will see if it can use any generic factory methods to resolve the type. For example this is how you could allow StrongInject to resolve an ImmutableArray:\n\n```csharp\npublic class ImmutableArrayModule\n{\n    [Factory] public static ImmutableArray\u003cT\u003e CreateImmutableArray\u003cT\u003e(T[] arr) =\u003e arr.ToImmutableArray();\n}\n```\n\nGeneric methods can also have constraints. StrongInject will ignore generic methods during resolution if the constraints do not match.\n\n##### Factory Of Methods\n\nSometimes you have a generic factory method which you don't want to use for everything, but only for specific use cases. For example, you may want to use another IOC container to resolve specific types, but don't want to write a separate factory method for each type. In such cases you can mark the method with any number of `FactoryOfAttribute`s, and it will act exactly like a normal factory method except it will only be used to resolve the types given in the `FactoryOfAttribute`s.\n\n```csharp\npublic partial class AspNetCoreControllerContainer : IContainer\u003cSomeAspNetCoreController\u003e\n{\n    private readonly IServiceProvider _serviceProvider;\n\n    public AspNetCoreControllerContainer(IServiceProvider serviceProvider)\n    {\n        _serviceProvider = serviceProvider;\n    }\n\n    [FactoryOf(typeof(ILogger\u003c\u003e), FactoryOf(typeof(IConfiguration))] private T GetService\u003cT\u003e() =\u003e _serviceProvider.GetRequiredService\u003cT\u003e();\n}\n```\n\nHere `GetService` will only be used to resolve `ILogger\u003cT\u003e` and `IConfiguration`.\n\n#### Decorators\n\nA decorator is a type which exposes a service by wrapping an underlying instance of the same service. Calls may pass straight through to the underlying service, or may be intercepted and custom behaviour applied. See https://en.wikipedia.org/wiki/Decorator_pattern.\n\nYou can register a type as a decorator using the `[RegisterDecorator(type, decoratedType)]` attribute. (If you're on the preview language version, you can use the generic `[RegisterDecorator\u003cTDecorator, TDecorated\u003e]`.)\n\nHere is an example of how you could time how long a call took using the decorator pattern and StrongInject.\n\n```csharp\nusing System;\nusing System.Diagnostics;\nusing StrongInject;\n\npublic class Foo {}\npublic interface IService\n{\n    Foo GetFoo()\n}\n\npublic class Service : IService\n{\n    public Foo GetFoo() =\u003e new Foo();\n}\n\npublic class ServiceTimingDecorator : IService\n{\n    private readonly IService _impl;\n    public ServiceTimingDecorator(IService impl) =\u003e _impl = impl;\n    public Foo GetFoo()\n    {\n        var watch = Stopwatch.StartNew();\n        var foo = _impl.GetFoo();\n        watch.Stop;\n        Console.WriteLine($\"Getting foo took {watch.ElapsedMilliseconds} ms\");\n        return foo;\n    }\n}\n\n[Register(typeof(Service), typeof(IService))]\n[RegisterDecorator(typeof(ServiceTimingDecorator), typeof(IService))]\npublic class Container : IContainer\u003cIService\u003e {}\n```\n\nStrongInject will resolve an instance of `Service`, and then wrap it in an instance of `ServiceTimingDecorator`. Whenever anyone asks for an `IService` they will get an instance of `ServiceTimingDecorator`.\n\nYou can't specify the scope of a decorator, as its scope is the same as that of the type it wraps.\n\nThe decorator constructor must have exactly one parameter of the decorated type, but can have any other parameters as well so long as they are not of the decorated type.\n\nInstances passed to [parameters of delegates](#delegate-support) are never decorated.\n\nYou can also define decorator factory methods, and even generic decorator factory methods via the `[DecoratorFactoryAttribute]`:\n\n```csharp\n[Register(typeof(Service), typeof(IService))]\npublic class Container : IContainer\u003cIService\u003e\n{\n    [DecoratorFactory] IService CreateDecorator(IService service) =\u003e new ServiceTimingDecorator(service);\n}\n```\n\nGeneric decorator factory methods gives you a powerful way to intercept resolution. For example you could theoretically use `Castle.DynamicProxy` along with a generic decorator factory to log every service thats created, or time all calls to all services:\n\n```csharp\nusing Castle.DynamicProxy;\nusing StrongInject;\nusing System;\nusing System.Diagnostics;\nusing System.Threading;\n\npublic class Interceptor : IInterceptor\n{\n    public void Intercept(IInvocation invocation)\n    {\n        var stopwatch = Stopwatch.StartNew();\n        invocation.Proceed();\n        stopwatch.Stop();\n        Console.WriteLine($\"Call to {invocation.Method.Name} took {stopwatch.ElapsedMilliseconds} ms\");\n    }\n}\n\npublic class Foo { }\npublic class Bar { }\n\npublic interface IService1\n{\n    void Frob();\n    Foo GetFoo();\n}\n\npublic interface IService2\n{\n    Bar UseBar(Bar bar);\n}\n\npublic class Service1 : IService1\n{\n    public void Frob()\n    {\n        Thread.Sleep(10);\n    }\n\n    public Foo GetFoo()\n    {\n        Thread.Sleep(20);\n        return new Foo();\n    }\n}\n\npublic class Service2 : IService2\n{\n    public Bar UseBar(Bar bar)\n    {\n        Thread.Sleep(30);\n        return bar;\n    }\n}\n\n[Register(typeof(Service1), typeof(IService1))]\n[Register(typeof(Service2), typeof(IService2))]\npublic partial class Container : IContainer\u003cIService1\u003e, IContainer\u003cIService2\u003e\n{\n    private readonly IInterceptor _interceptor = new Interceptor();\n    private readonly ProxyGenerator _proxyGenerator = new ProxyGenerator();\n\n    [DecoratorFactory]\n    T Time\u003cT\u003e(T t) where T : class\n    {\n        if (typeof(T).IsInterface)\n        {\n            return _proxyGenerator.CreateInterfaceProxyWithTarget(t, _interceptor);\n        }\n        else\n        {\n            return _proxyGenerator.CreateClassProxyWithTarget(t, _interceptor);\n        }\n    }\n}\n\npublic class Program\n{\n    public static void Main()\n    {\n        var container = new Container();\n        container.Run\u003cIService1\u003e(x =\u003e\n        {\n            x.Frob();\n            _ = x.GetFoo();\n        });\n        container.Run\u003cIService2\u003e(x =\u003e _ = x.UseBar(new Bar()));\n    }\n}\n```\n\nThe above program will print something like:\n\n```\nCall to Service1.Frob took 20 ms\nCall to Service1.GetFoo took 26 ms\nCall to Service2.UseBar took 42 ms\n```\n\nYou can register multiple decorators for a type, and they will all be applied. As of now there is no way to control in which order they are applied, but the order is deterministic.\n\nIf you register an `[Instance]` and don't want it decorated, you can use `Options.DoNotDecorate`: `[Instance(Options.DoNotDecorate)]`.\n\nDecorators are not disposed by default. For more information see [the wiki](https://github.com/YairHalberstadt/stronginject/wiki/Decorators#disposal).\n\n#### Providing registrations at runtime or integrating with other IOC containers\n\nWhat if you need to provide configuration for a registration at runtime? Or alternatively what if you need to integrate with an existing container?\n\nWe've already mentioned above that you can mark instance fields or properties on a container as `[Instance]`s. This allows you to access information only available at runtime during resolution:\n\n```csharp\nusing StrongInject;\n\npublic class A\n{\n    public A(Configuration configuration){}\n}\n\npublic class Configuration {}\n\n[Register(typeof(A))]\npublic partial class Container : IContainer\u003cA\u003e\n{\n    [Instance] Configuration _configuration;\n    public Container(Configuration configuration) =\u003e _configuration = configuration;\n}\n```\n\nIn some cases the runtime fields you need might be of a type that you would be hesitant to register, such as bool, or string. In such cases you can use factory methods to only access them where appropriate:\n\n```csharp\nusing StrongInject;\n\npublic interface IInterface { }\npublic class A : IInterface { }\npublic class B : IInterface { }\n\n[Register(typeof(A))]\n[Register(typeof(B))]\npublic partial class Container : IContainer\u003cIInterface\u003e\n{\n    private readonly bool _useB;\n    public Container(bool useB) =\u003e _useB = useB;\n\n    [Factory]\n    IInterface GetInterfaceInstance(Func\u003cA\u003e a, Func\u003cB\u003e b) =\u003e _useB ? b() : a();\n}\n```\n\nIn some cases though you need greater control over the disposal of the created instances. To do so you can make an `Instance` field implementing `IFactory\u003cT\u003e` or `IAsyncFactory\u003cT\u003e` and use `Options.UseAsFactory`. For example here's how you could integrate with Autofac:\n\n```csharp\nusing StrongInject;\n\npublic class A\n{\n    public A(B b){} \n}\npublic class B {}\n\npublic class AutofacFactory\u003cT\u003e(Autofac.IContainer autofacContainer) : IFactory\u003cT\u003e where T : class\n{\n    private readonly ConcurrentDictionary\u003cT, Autofac.Owned\u003cT\u003e\u003e _ownedDic = new();\n    private readonly Autofac.IContainer _autofacContainer;\n    public AutofacFactory(Autofac.IContainer autofacContainer) =\u003e _autofacContainer = autofacContainer;\n    public T Create()\n    {\n        var owned = _autofacContainer.Resolve\u003cOwned\u003cT\u003e\u003e();\n        _ownedDic[owned.Value] = owned;\n        return owned.Value;\n    };\n    public void Release(T instance)\n    {\n        if (_ownedDic.TryGetValue(instance, out var owned))\n            owned.Dispose();\n    }\n}\n\n[Register(typeof(A))]\npublic partial class Container : IContainer\u003cA\u003e\n{\n    [Instance(Options.AsImplementedInterfacesAndUseAsFactory)] private readonly AutofacFactory\u003cB\u003e _autofacFactory;\n    public Container(AutofacFactory\u003cB\u003e autofacFactory) =\u003e _autofacFactory = autofacFactory;\n}\n```\n\nThis registers `AutofacFactory\u003cB\u003e` as all implemented interfaces, namely `IFactory\u003cB\u003e`. Since this is a factory, this also becomes a registration for `B` as well.\n\n`Create` is called once per resolution (equivalent to Instance Per Resolution scope). This can be adjusted further by registering it as `[Instance(Options.AsImplementedInterfacesAndUseAsFactory | Options.FactoryTargetScopeShouldBeSingleInstance)` for example.\n\n#### How StrongInject picks which registration to use\n\nIt is possible for there to be multiple registrations for a type. In such a case resolving an instance of the type will result in an error, unless there is a best registration. The rule for picking the best registration is simple - any registration defined by a module is better than registrations defined on other modules that that module imports. \n\nSo for example, imagine there is a `Container`, and two modules, `ModuleA` and `ModuleB`.\n\nIf all three define a registration for `SomeInterface`, then the one defined on the container will always be the best.\n\nIf just `ModuleA` and `ModuleB` define a registration for `SomeInterface` then things will depend:\n\n- If `Container` imports both modules, resolving `SomeInterface` will always result in an error (even if `ModuleA` imports `ModuleB` or vice versa).\n- If `Container` imports `ModuleA`, and `ModuleA` imports `ModuleB`, then `ModuleA`'s registration will be best.\n- If `Container` imports `ModuleB`, and `ModuleB` imports `ModuleA`, then `ModuleB`'s registration will be best.\n\nTo fix errors as a result of multiple registrations for a type, the simplest thing to do is to add a single best registration directly to the container. If the container already has multiple registrations for the type, then move those registrations to a separate module and import them.\n\n### Delegate Support\n\nStrongInject can automatically resolve non-void returning delegates even if they're not registered. It tries to resolve the return type. The delegate parameters can be used in the resolution, and will override any existing resolutions.\n\nThere are two reasons you might want to use delegate resolution:\n\n1. To return a new instance of the return type on every call:\n\n```csharp\nusing System;\nusing StrongInject;\n\npublic class A\n{\n  public A(Func\u003cB\u003e fB) =\u003e Console.WriteLine(fB() != fB()); //prints true\n}\n\npublic class B{}\n\n[Register(typeof(A))]\n[Register(typeof(B))]\npublic class Container : IContainer\u003cA\u003e {}\n```\n\n2. To provide parameters which are not available at resolution time:\n\n```csharp\nusing System;\nusing StrongInject;\n\npublic class Server\n{\n  private Handler _frobbingHandler;\n  private Handler _nonFrobbingHandler;\n  public Server(Func\u003cbool, Handler\u003e handlerFunc) =\u003e (_frobbingHandler, _nonFrobbingHandler) = (handlerFunc(true), handlerFunc(false));\n  \n  public bool HandleRequest(Request request, bool shouldFrob) =\u003e shouldFrob ? _frobbingHandler.HandleRequest(request) : _nonFrobbingHandler.HandleRequest(request);\n}\n\npublic class Handler\n{\n  public Handler(bool shouldFrob) =\u003e ...\n}\n\n[Register(typeof(Server))]\n[Register(typeof(Handler))]\npublic class Container : IContainer\u003cServer\u003e {}\n```\n\nIf the return type can only be resolved asynchronously (see [below](#async-support)), the delegate must return `Task\u003cT\u003e` or `ValueTask\u003cT\u003e`. e.g.\n\n```csharp\nusing System;\nusing StrongInject;\nusing System.Threading.Tasks;\n\npublic class Server\n{\n  private Func\u003cbool, Task\u003cHandler\u003e\u003e _handlerFunc;\n  public Server(Func\u003cbool, Task\u003cHandler\u003e\u003e handlerFunc) =\u003e _handlerFunc = handlerFunc;\n  \n  public async Task\u003cbool\u003e HandleRequest(Request request, bool shouldFrob) =\u003e (await _handlerFunc(shouldFrob)).HandleRequest(request);\n}\n\npublic class Handler : IRequiresAsyncInitialization\n{\n  public Handler(bool shouldFrob) =\u003e ...\n  public async ValueTask InitializeAsync() =\u003e ...\n}\n\n[Register(typeof(Server))]\n[Register(typeof(Handler))]\npublic class Container : IContainer\u003cServer\u003e {}\n```\n\n### `Owned\u003cT\u003e` support\n\nUsing `Owned\u003cT\u003e` instead of `T` gives a component the control over when the `T` instance and all its dependencies are released back to the container. You access the `T` instance using the `Owned\u003cT\u003e.Value` property, and you dispose the `Owned\u003cT\u003e` instance to release the `T` instance and its dependencies back to the container. It’s your responsibility to call `Owned\u003cT\u003e.Dispose()` when you’re ready. If you don’t, the `T` instance and all its dependencies will never be cleaned up, not even when the container itself is disposed.\n\n`Owned\u003cT\u003e` offers a clean alternative to disposing the `T` instance directly. Disposing `T` directly can lead to leaks where the dependencies of the `T` instance itself are not disposed or released back to the container soon enough. Advanced situations like pooling also require `Owned\u003cT\u003e` to release the `T` back to the pool without disposing it.\n\nInjecting `Owned\u003cT\u003e` or delegates returning `Owned\u003cT\u003e` is enabled out of the box, and so are the `AsyncOwned\u003cT\u003e` versions of these. `AsyncOwned\u003cT\u003e` will be required to be used instead of `Owned\u003cT\u003e` when the `T` in question or any of its dependencies require asynchronous disposal.\n\nThe typical scenario is when you combine this with delegates by injecting `Func\u003cOwned\u003cY\u003e\u003e` or `Func\u003cX, Owned\u003cY\u003e\u003e` into a component. This enables the component to acquire and release `Y` instances as many times as it needs, possibly with varying parameters, and possibly overlapping with each other before releasing them back to the container. Here’s one such usage:\n\n```csharp\nusing Microsoft.Data.SqlClient;\nusing Microsoft.EntityFrameworkCore;\nusing StrongInject;\nusing System;\nusing System.Threading.Tasks;\n\n[Register(typeof(SomeViewModel))]\n[Register(typeof(SomeDbContext))]\npublic partial class Container : IContainer\u003cSomeViewModel\u003e\n{\n    [Factory]\n    public static SqlConnection CreateSqlConnection()\n    {\n        throw new NotImplementedException();\n    }\n}\n\npublic class SomeViewModel\n{\n    private readonly Func\u003cOwned\u003cSomeDbContext\u003e\u003e dbContextFactory;\n\n    public SomeViewModel(Func\u003cOwned\u003cSomeDbContext\u003e\u003e dbContextFactory)\n    {\n        this.dbContextFactory = dbContextFactory;\n    }\n\n    public async Task SaveAsync(string newName)\n    {\n        // Using Func\u003cOwned\u003cSomeDbContext\u003e\u003e instead of Func\u003cSomeDbContext\u003e ensures that the context will not be\n        // disposed while this method is still using it, even if SomeViewModel is released back to the container.\n\n        // Using Func\u003cOwned\u003cSomeDbContext\u003e\u003e instead of Owned\u003cSomeDbContext\u003e gives the ability for SaveAsync to\n        // get a new SomeDbContext instance that is not being used anywhere else, so overlapping calls to SaveAsync\n        // are no problem.\n\n        using Owned\u003cDbContext\u003e dbContext = dbContextFactory.Invoke();\n\n        dbContext.Value.Set\u003cSomeEntity\u003e().Add(new SomeEntity { Name = newName });\n        await dbContext.Value.SaveChangesAsync();\n    }\n}\n\npublic class SomeDbContext : DbContext\n{\n    public SomeDbContext(SqlConnection connection)\n        : base(new DbContextOptionsBuilder().UseSqlServer(connection).Options)\n    {\n    }\n}\n\npublic class SomeEntity\n{\n    public string Name { get; set; }\n}\n```\n\n\u003e ℹ **Coming from Castle Windsor?**\n\u003e\n\u003e Injecting a delegate such as `Func\u003c…, Owned\u003cT\u003e\u003e` is a concept which maps 1:1 with Castle Windsor’s _typed factories_ feature. Castle Windsor’s feature can auto-implement an interface you define, such as `IFactory\u003cT\u003e` with `T Resolve(…)` and `void Release(T)` methods.\n\u003e\n\u003e To convert to the equivalent feature in StrongInject:\n\u003e\n\u003e | Instead of this | Do this |\n\u003e |-|-|\n\u003e | Inject `IFactory\u003cT\u003e` | Inject `Func\u003cOwned\u003cT\u003e\u003e` |\n\u003e | Call `IFactory\u003cT\u003e.Resolve()` | Invoke the `Func\u003cOwned\u003cT\u003e\u003e` delegate |\n\u003e | Call `IFactory\u003cT\u003e.Release(instance)` | Call `Owned\u003cT\u003e.Dispose()` (prefer a `using` statement) |\n\u003e\n\u003e If the `IFactory\u003cT\u003e.Resolve` method takes parameters, such as `IFactory\u003cT\u003e.Resolve(A param1, B param2)`, inject `Func\u003cA, B, Owned\u003cT\u003e\u003e` instead.\n\n### Post Constructor Initialization\n\nIf your type implements `IRequiresInitialization`, `Initialize` will be called after construction.\nWhilst this is only useful in a few edge cases for synchronous methods, `IRequiresAsyncInitialization` is extremely useful as constructors cannot be async. Therefore I'll leave an example of using this API for the section on async support. \n\n### Async Support\n\nEvery interface used by StrongInject has an asynchronous counterpart.\nThere's `IAsyncContainer`, `IAsyncFactory` and `IRequiresAsyncInitialization`.\n\nYou can resolve an instance of `T` asynchronously from an `IAsyncContainer\u003cT\u003e` by calling `StrongInject.AsyncContainerExtensions.RunAsync`. RunAsync has overloads allowing you to pass in sync or async lambdas. As such `IAsyncContainer\u003cT\u003e` is useful even if resolution is completely synchronous if usage is asynchronous.\n\nIt is an error resolving `T` in an `IContainer\u003cT\u003e` if it depends on an asynchronous dependency.\n\nA type can implement both `IContainer\u003cT1\u003e` and `IAsyncContainer\u003cT2\u003e`. They will share single instance dependencies.\n\nHere is a full fledged example where data will be loaded from the database as part of resolution using `IRequiresAsyncInitialization`:\n\n```csharp\nusing StrongInject;\nusing System;\nusing System.Collections.Generic;\nusing System.Threading;\nusing System.Threading.Tasks;\n\npublic interface IDb\n{\n    Task\u003cDictionary\u003cstring, string\u003e\u003e GetUserPasswordsAsync();\n}\n\npublic class PasswordChecker : IRequiresAsyncInitialization, IAsyncDisposable\n{\n    private readonly IDb _db;\n\n    private Dictionary\u003cstring, string\u003e _userPasswords;\n\n    private Timer _timer;\n\n    public PasswordChecker(IDb db)\n    {\n        _db = db;\n    }\n\n    public async ValueTask InitializeAsync()\n    {\n        _userPasswords = await _db.GetUserPasswordsAsync();\n        _timer = new Timer(async _ =\u003e { _userPasswords = await _db.GetUserPasswordsAsync(); }, null, 60000, 60000);\n    }\n\n    public bool CheckPassword(string user, string password) =\u003e _userPasswords.TryGetValue(user, out var correctPassword) \u0026\u0026 password == correctPassword;\n\n    public ValueTask DisposeAsync()\n    {\n        return _timer.DisposeAsync();\n    }\n}\n\n[Register(typeof(PasswordChecker), Scope.SingleInstance)]\npublic partial class Container : IAsyncContainer\u003cPasswordChecker\u003e\n{\n    private readonly IDb _db;\n\n    public Container(IDb db)\n    {\n        _db = db;\n    }\n\n    [Factory]\n    IDb GetDb() =\u003e _db;\n}\n\npublic static class Program\n{\n  public static async Task Main(string[] args)\n  {\n    await new Container(new Db()).RunAsync(x =\u003e \n      Console.WriteLine(x.CheckPassword(args[0], args[1])\n        ? \"Password is valid\"\n        : \"Password is invalid\"));\n  }\n}\n```\n\n#### Parallel Resolution\n\nStrongInject makes the assumption that async dependencies will usually be doing IO. In order to increase performance it kicks off all async tasks in parallel as early as it can, and only awaits them once it's completed resolving all dependencies that don't require them. For example, if most of your components call the database as part of resolution, they will all do so in parallel rather than one after the other.\n\nThis improves async resolution time hugely - instead of resolution time being the sum of the time to resolve all components, it's the the amount of time it takes to resolve the longest chain of dependent components, no matter how many other components there are.\n\nWhat this means is that components used as part of async resolution should be thread safe. If they are not, mark them as `InstancePerDependency`, which will ensure that they are only ever used by one thread of resolution at a time.\n\n### Resolving all instances of a type\n\nWhen resolving an array type, if there are no user provided registrations for the array type, the array will be created by resolving all registrations (including generic registrations) for the element type, and filling the array with these instances.\n\nFor example:\n\n```csharp\npublic class A : IInterface {}\npublic class B : IInterface {}\npublic interface IInterface {}\n\n[Register(typeof(A), typeof(IInterface))]\n[Register(typeof(B), typeof(IInterface))]\npublic class Container : IContainer\u003cIInterface[]\u003e\n```\n\nThis will resolve an array containing an instance of type `A` and an instance of type `B`.\n\nThe contents of the array are arbitrary but deterministic. A new array is created for every dependency, so users are free to mutate it.\n\nNote that duplicate registrations will be deduplicated, so in the following case:\n\n```csharp\npublic class A : IInterface {}\npublic interface IInterface {}\n\n[Register(typeof(A), typeof(IInterface))]\n[Register(typeof(A), typeof(IInterface))]\npublic class Container : IContainer\u003cIInterface[]\u003e\n```\n\nThe array will contain 1 item, but in this case:\n\n```csharp\npublic class A : IInterface {}\npublic interface IInterface {}\n\n[Register(typeof(A), typeof(IInterface))]\n[Register(typeof(A), Scope.SingleInstance, typeof(IInterface))]\npublic class Container : IContainer\u003cIInterface[]\u003e\n```\n\nIt will contain 2 items.\n\n### Optional Parameters\n\nIf a parameter to a type or method is optional, StrongInject will not error if it cannot be resolved, and will instead just use the default value.\n\nAn example of where this can be useful is for providing a default instance of an interface if none is registered:\n\n```csharp\npublic class DefaultImplementation : IInterface {}\npublic interface IInterface {}\n\n[Register(typeof(DefaultImplementation))]\npublic class Module\n{\n  [Decorator] GetIInterface(IInterface? impl = null, DefaultImplementation defaultImpl) =\u003e impl ?? defaultImpl;\n}\n```\n\n### Disposal\n\nOnce a call to `Run` or `RunAsync` is complete, any Instance Per Resolution or Instance Per Dependency instances created as part of the call to `Run` or `RunAsync` will be disposed.\n\nSimilarly when an `Owned\u003cT\u003e` is disposed, any Instance Per Resolution or Instance Per Dependency instances created as part of resolving `T` will be disposed.\n\nIn `RunAsync`/`ResolveAsync` if the types implement `IAsyncDisposable` it will be preferred over `IDisposable`. `Dispose` and `DisposeAsync` will not both be called, just `DisposeAsync`.\nIn `Run`/`Resolve`, `IAsyncDisposable` will be ignored. Only `Dispose` will ever be called.\n\nSince `IFactory\u003cT\u003e` is free to create a new instance every time or return a singleton, StrongInject cannot call dispose directly. Instead it calls `IFactory\u003cT\u003e.Release(T instance)`. The factory is then free to dispose the class or not. When referencing the .NET Standard 2.1 package `Release` has a default implementation which does nothing. You only need to implement it if you want custom behaviour. If you reference the .NET Standard 2.0 package you will need to implement it either way.\n\nSingle Instance dependencies and their dependencies are disposed when the container is disposed. If the container implements `IAsyncDisposable` it must be disposed asynchronously even if it also implements `IDisposable`.\n\nNote that dependencies may not be disposed in the following circumstances:\n1. Resolution of a SingleInstance dependency throws.\n2. Disposal of other dependencies throws.\n\nWhen either of these happen it is most likely best to restart the application anyway, as a safe recovery is very unlikely.\n\n### Thread Safety\n\nStrongInject provides the following thread safety guarantees:\n1. Resolution is thread safe, so long as it doesn't call back into the container recursively (e.g. a factory calling `container.RunAsync`).\n2. If the container is disposed during resolution, then either dependencies will be created by the resolution, and will then be disposed, or resolution will throw and no dependencies will be created. Dependencies will not be created and then not disposed.\n3. A SingleInstance dependency will never be created more than once.\n\n### Inbuilt Modules\n\nStrongInject provides a number of inbuilt modules which can be used 'out of the box' in the `StrongInject.Modules` namespace for the most commonly required functionality. You still need to import these modules via `RegisterModule`, although you can get all of the less opinionated modules in one go by importing the `StandardModule`.\n\nAt the moment the following modules are provided:\n\n1. `LazyModule` (registers `Lazy\u003cT\u003e`)\n1. `CollectionsModule` (registers `IEnumerable\u003cT\u003e`, `IReadOnlyList\u003cT\u003e` and `IReadOnlyCollection\u003cT\u003e`)\n1. `ValueTupleModule` (registers all tuples from sizes 2 till 10)\n1. `SafeImmutableArrayModule` (registers `ImmutableArray\u003cT\u003e`)\n1. `UnsafeImmutableArrayModule` (provides a faster non-copying registration for `ImmutableArray\u003cT\u003e` which cannot be used if a custom registration for `T[]` exists)\n\nAt the moment the `StandardModule` imports `lazyModule`, `CollectionsModule` and `ValueTuple` module.\n\nIf you would like more modules/registrations added please open an issue.\n\n## Product Roadmap\n\nhttps://github.com/YairHalberstadt/stronginject/projects/1\n\n## Contributing\n\nPlease do open issues if you spot any bugs, or would like to suggest new features/API changes.\n\nPlease feel free to work on any open issue and open a PR. Ideally open an issue before working on something, so that the effort doesn't go to waste if it's not suitable.\n\nNote that I will tend to be very available if you need any help whilst contributing - see next section about how to contact me.\n\n## Need Help?\n\nI tend to hang around on Gitter so feel free to chat at https://gitter.im/stronginject/community.\n\nYou can also [open an issue](https://github.com/YairHalberstadt/stronginject/issues/new/choose), ask on [Stack Overflow](https://stackoverflow.com/questions/ask), or tag [me](https://twitter.com/HalberstadtYair) on twitter.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FYairHalberstadt%2Fstronginject","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FYairHalberstadt%2Fstronginject","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FYairHalberstadt%2Fstronginject/lists"}