Pure.DI is a compile-time dependency injection (DI) code generator. Supports .NET starting with .NET Framework 2.0, released 2005-10-27, and all newer versions.
- .NET SDK 6.0.4+
Required for compilation. Projects can target older frameworks (e.g., .NET Framework 2.0). - C# 8+
Only required for projects using the Pure.DI source generator. Other projects support any C# version.
Pure.DI is a .NET code generator designed to produce clean, efficient dependency injection logic. By leveraging basic language constructs, it generates straightforward code indistinguishable from manual implementationβessentially composing objects through nested constructor invocations. Unlike traditional DI frameworks, Pure.DI avoids reflection and dynamic instantiation entirely, eliminating performance penalties associated with runtime overhead.
All analysis of object, constructor, and method graphs occurs at compile time. Pure.DI proactively detects and alerts developers to issues such as missing dependencies, cyclic references, or dependencies unsuitable for injectionβensuring these errors are resolved before execution. This approach guarantees that developers cannot produce a program vulnerable to runtime crashes caused by faulty dependency wiring. The validation process operates seamlessly alongside code development, creating an immediate feedback loop: as you modify your code, Pure.DI verifies its integrity in real time, effectively delivering tested, production-ready logic the moment changes are implemented.
The pure dependency injection approach introduces no runtime dependencies and avoids .NET reflection , ensuring consistent execution across all supported platforms. This includes the Full .NET Framework 2.0+, .NET Core, .NET 5+, UWP/Xbox, .NET IoT, Unity, Xamarin, Native AOT, and beyond. By decoupling runtime constraints, it preserves predictable behavior regardless of the target environment.
The Pure.DI API is intentionally designed to closely mirror the APIs of mainstream IoC/DI frameworks. This approach ensures developers can leverage their existing knowledge of dependency injection patterns without requiring significant adaptation to a proprietary syntax.
Pure.DI recommends utilizing dedicated marker types rather than relying on open generics. This approach enables more precise construction of object graphs while allowing developers to fully leverage the capabilities of generic types.
Pure.DI allows to view and debug the generated code, making debugging and testing easier.
Pure.DI provides native support for numerous Base Class Library (BCL) types out of the box without any extra effort.
Pure.DI is designed for high-performance applications where speed and minimal memory consumption are critical.
Pure.DI is suitable for projects where code cleanliness and minimalism are important factors.
Pure.DI can handle complex dependencies and provides flexible configuration options.
Its high performance, zero memory consumption/preparation overhead, and lack of dependencies make it ideal for building libraries and frameworks.
NuGet package | Description |
---|---|
Pure.DI | DI source code generator |
Pure.DI.Abstractions | Abstractions for Pure.DI |
Pure.DI.Templates | Template package, for creating projects from the shell/command line |
Pure.DI.MS | Add-ons on Pure.DI to work with Microsoft DI |
interface IBox<out T>
{
T Content { get; }
}
interface ICat
{
State State { get; }
}
enum State { Alive, Dead }
record CardboardBox<T>(T Content): IBox<T>;
class ShroedingersCat(Lazy<State> superposition): ICat
{
// The decoherence of the superposition
// at the time of observation via an irreversible process
public State State => superposition.Value;
}
Important
Our abstraction and implementation knows nothing about the magic of DI or any frameworks.
Add the Pure.DI package to your project:
Let's bind the abstractions to their implementations and set up the creation of the object graph:
DI.Setup(nameof(Composition))
// Models a random subatomic event that may or may not occur
.Bind().As(Singleton).To<Random>()
// Quantum superposition of two states: Alive or Dead
.Bind().To((Random random) => (State)random.Next(2))
.Bind().To<ShroedingersCat>()
// Cardboard box with any contents
.Bind().To<CardboardBox<TT>>()
// Composition Root
.Root<Program>("Root");
Note
In fact, the Bind().As(Singleton).To<Random>()
binding is unnecessary since Pure.DI supports many .NET BCL types out of the box, including Random. It was added just for the example of using the Singleton lifetime.
The above code specifies the generation of a partial class named Composition, this name is defined in the DI.Setup(nameof(Composition))
call. This class contains a Root property that returns a graph of objects with an object of type Program as the root. The type and name of the property is defined by calling Root<Program>("Root")
. The code of the generated class looks as follows:
partial class Composition
{
private readonly Lock _lock = new Lock();
private Random? _random;
public Program Root
{
get
{
var stateFunc = new Func<State>(() => {
if (_random is null)
lock (_lock)
if (_random is null)
_random = new Random();
return (State)_random.Next(2)
});
return new Program(
new CardboardBox<ICat>(
new ShroedingersCat(
new Lazy<State>(
stateFunc))));
}
}
public T Resolve<T>() { ... }
public T Resolve<T>(object? tag) { ... }
public object Resolve(Type type) { ... }
public object Resolve(Type type, object? tag)) { ... }
}
Class diagram
classDiagram
ShroedingersCat --|> ICat
CardboardBoxαΈICatα³ --|> IBoxαΈICatα³
CardboardBoxαΈICatα³ --|> IEquatableαΈCardboardBoxαΈICatα³α³
Composition ..> Program : Program Root
State o-- "Singleton" Random : Random
ShroedingersCat *-- LazyαΈStateα³ : LazyαΈStateα³
Program *-- CardboardBoxαΈICatα³ : IBoxαΈICatα³
CardboardBoxαΈICatα³ *-- ShroedingersCat : ICat
LazyαΈStateα³ o-- "PerBlock" FuncαΈStateα³ : FuncαΈStateα³
FuncαΈStateα³ *-- State : State
namespace Sample {
class CardboardBoxαΈICatα³ {
<<record>>
+CardboardBox(ICat Content)
}
class Composition {
<<partial>>
+Program Root
+ T ResolveαΈTα³()
+ T ResolveαΈTα³(object? tag)
+ object Resolve(Type type)
+ object Resolve(Type type, object? tag)
}
class IBoxαΈICatα³ {
<<interface>>
}
class ICat {
<<interface>>
}
class Program {
<<class>>
+Program(IBoxαΈICatα³ box)
}
class ShroedingersCat {
<<class>>
+ShroedingersCat(LazyαΈStateα³ superposition)
}
class State {
<<enum>>
}
}
namespace System {
class FuncαΈStateα³ {
<<delegate>>
}
class IEquatableαΈCardboardBoxαΈICatα³α³ {
<<interface>>
}
class LazyαΈStateα³ {
<<class>>
}
class Random {
<<class>>
+Random()
}
}
You can see the class diagram at any time by following the link in the comment of the generated class:
Obviously, this code does not depend on other libraries, does not use type reflection or any other tricks that can negatively affect performance and memory consumption. It looks like an efficient code written by hand. At any given time, you can study it and understand how it works.
The public Program Root { get; }
property here is a Composition Root, the only place in the application where the composition of the object graph for the application takes place. Each instance is created by only basic language constructs, which compiles with all optimizations with minimal impact on performance and memory consumption. In general, applications may have multiple composition roots and thus such properties. Each composition root must have its own unique name, which is defined when the Root<T>(string name)
method is called, as shown in the above code.
class Program(IBox<ICat> box)
{
// Composition Root, a single place in an application
// where the composition of the object graphs
// for an application take place
static void Main() => new Composition().Root.Run();
private void Run() => Console.WriteLine(box);
}
Pure.DI creates efficient code in a pure DI paradigm, using only basic language constructs as if you were writing code by hand. This allows you to take full advantage of Dependency Injection everywhere and always, without any compromise!
The full analog of this application with top-level statements can be found here.
Just try creating a project from scratch!
Install the projects template
dotnet new install Pure.DI.Templates
In some directory, create a console application
dotnet new di
And run it
dotnet run
Pure.DI
BindAttribute
Indicates that a property or method can be automatically added as a binding.
internal class DependencyProvider { [Bind()] public Dependency Dep => new Dependency(); }internal class DependencyProvider { [Bind(typeof(IDependency<TT>), Lifetime.Singleton)] public Dependency GetDep<T>() => new Dependency(); }internal class DependencyProvider { [Bind(typeof(IDependency), Lifetime.PerResolve, "some tag")] public Dependency GetDep(int id) => new Dependency(id); }See also Exposed.
Constructor BindAttribute(System.Type,Pure.DI.Lifetime,System.Object[])
Creates an attribute instance.
Buckets`1
For internal use.
CannotResolveException
Represents an exception thrown when a required composition root cannot be resolved.
Constructor CannotResolveException(System.String,System.Type,System.Object)
Initializes a new instance of the CannotResolveException class with a specified error message, type, and optional tag describing the resolution failure.
parameter message - A user-friendly message that describes the error that occurred during the resolution process. The message should be clear and informative, providing enough context to understand the nature of the failure.
parameter type - The Type used to resolve a composition root.
parameter tag - The tag used to resolve a composition root.
Constructor CannotResolveException(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)
Initializes a new instance of the CannotResolveException class with serialized data.
parameter info - The object that holds the serialized object data.
parameter context - The contextual information about the source or destination.
Property Type
Gets the type used to resolve a composition root.
Property Tag
Gets the tag used to resolve a composition root.
CompositionKind
Determines how the partial class will be generated. The Setup(System.String,Pure.DI.CompositionKind) method has an additional argument
kind
, which defines the type of composition:DI.Setup("BaseComposition", CompositionKind.Internal);See also Setup(System.String,Pure.DI.CompositionKind).
Field Public
This value is used by default. If this value is specified, a normal partial class will be generated.
Field Internal
If this value is specified, the class will not be generated, but this setting can be used by other users as a baseline. The API call DependsOn(System.String[]) is mandatory.
Field Global
No partial classes will be created when this value is specified, but this setting is the baseline for all installations in the current project, and the API call DependsOn(System.String[]) is not required.
DependencyAttribute
Combines injection tagging and ordering capabilities in a single attribute. Allows simultaneous specification of both tag and ordinal for dependency injection points.
parameter tag - Identifies the specific dependency variation to inject. See also Tags(System.Object[]).
parameter ordinal - Determines injection order priority (lower values execute first).
See also OrdinalAttribute.
See also TagAttribute.
Constructor DependencyAttribute(System.Object,System.Int32)
Initializes an attribute instance with optional tag and priority.
parameter tag - Identifies a specific dependency variation. See also Tags(System.Object[]).
parameter ordinal - Injection execution priority (0 = highest priority). Default: 0.
DI
An API for a Dependency Injection setup.
See also Setup(System.String,Pure.DI.CompositionKind).
Method Setup(System.String,Pure.DI.CompositionKind)
Begins the definitions of the Dependency Injection setup chain.
interface IDependency; class Dependency: IDependency; interface IService; class Service(IDependency dependency): IService; DI.Setup("Composition") .Bind<IDependency>().To<Dependency>() .Bind<IService>().To<Service>() .Root<IService>("Root");
parameter compositionTypeName - An optional argument specifying the partial class name to generate.
parameter kind - An optional argument specifying the kind of setup. Please CompositionKind for details. It defaults to
Public
.returns Reference to the setup continuation chain.
GenericTypeArgumentAttribute
Represents a generic type argument attribute. It allows you to create custom generic type argument such as TTS, TTDictionary`2, etc.
[GenericTypeArgument] internal interface TTMy: IMy { }See also GenericTypeArgumentAttribute``1.
See also GenericTypeArgument``1.
Hint
Provides configuration hints for fine-tuning code generation behavior.
// Resolve = Off DI.Setup("Composition") .Bind<IDependency>().To<Dependency>();or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition") .Hint(Hint.Resolve, "Off") .Bind<IDependency>().To<Dependency>();See also Hint(Pure.DI.Hint,System.String).
Field Resolve
Enables/disables generation of Resolve methods. Default:
On
.// Resolve = Off DI.Setup("Composition") .Bind<IDependency>().To<Dependency>();or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition") .Hint(Hint.Resolve, "Off") .Bind<IDependency>().To<Dependency>();Field OnNewInstance
Enables/disables generation of OnNewInstance hooks. Default:
Off
.// OnNewInstance = On DI.Setup("Composition") .Bind<IDependency>().To<Dependency>();or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition") .Hint(Hint.OnNewInstance, "On") .Bind<IDependency>().To<Dependency>();Field OnNewInstancePartial
Enables/disables partial method generation for OnNewInstance. Default:
On
.// OnNewInstancePartial = On DI.Setup("Composition") .Bind<IDependency>().To<Dependency>();or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition") .Hint(Hint.OnNewInstancePartial, "On") .Bind<IDependency>().To<Dependency>();Field OnNewInstanceImplementationTypeNameRegularExpression
Regex filter for instance types in OnNewInstance hooks. Default:
.+
.// OnNewInstanceImplementationTypeNameRegularExpression = Dependency DI.Setup("Composition") .Bind<IDependency>().To<Dependency>();or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition") .Hint(Hint.OnNewInstanceImplementationTypeNameRegularExpression, "Dependency") .Bind<IDependency>().To<Dependency>();Field OnNewInstanceImplementationTypeNameWildcard
Wildcard filter for instance types in OnNewInstance hooks. Default:
*
.// OnNewInstanceImplementationTypeNameWildcard = *Dependency DI.Setup("Composition") .Bind<IDependency>().To<Dependency>();or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition") .Hint(OnNewInstanceImplementationTypeNameWildcard, "*Dependency") .Bind<IDependency>().To<Dependency>();Field OnNewInstanceTagRegularExpression
Regex filter for tags in OnNewInstance hooks. Default:
.+
.// OnNewInstanceTagRegularExpression = IDependency DI.Setup("Composition") .Bind<IDependency>().To<Dependency>();or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition") .Hint(Hint.OnNewInstanceTagRegularExpression, "IDependency") .Bind<IDependency>().To<Dependency>();Field OnNewInstanceTagWildcard
Wildcard filter for tags in OnNewInstance hooks. Default:
*
.// OnNewInstanceTagWildcard = *IDependency DI.Setup("Composition") .Bind<IDependency>().To<Dependency>();or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition") .Hint(Hint.OnNewInstanceTagWildcard, "*IDependency") .Bind<IDependency>().To<Dependency>();Field OnNewInstanceLifetimeRegularExpression
Regex filter for lifetimes in OnNewInstance hooks. Default:
.+
.// OnNewInstanceLifetimeRegularExpression = Singleton DI.Setup("Composition") .Bind<IDependency>().To<Dependency>();or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition") .Hint(Hint.OnNewInstanceLifetimeRegularExpression, "Singleton") .Bind<IDependency>().To<Dependency>();Field OnNewInstanceLifetimeWildcard
Wildcard filter for lifetimes in OnNewInstance hooks. Default:
*
.// OnNewInstanceLifetimeWildcard = *Singleton DI.Setup("Composition") .Bind<IDependency>().To<Dependency>();or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition") .Hint(Hint.OnNewInstanceLifetimeWildcard, "*Singleton") .Bind<IDependency>().To<Dependency>();Field OnDependencyInjection
Enables/disables dependency injection interception hooks. Default:
Off
.// OnDependencyInjection = On DI.Setup("Composition") .Bind<IDependency>().To<Dependency>();or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition") .Hint(Hint.OnDependencyInjection, "On") .Bind<IDependency>().To<Dependency>();Field OnDependencyInjectionPartial
Enables/disables partial method generation for dependency injection hooks. Default:
On
.// OnDependencyInjectionPartial = On DI.Setup("Composition") .Bind<IDependency>().To<Dependency>();or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition") .Hint(Hint.OnDependencyInjectionPartial, "On") .Bind<IDependency>().To<Dependency>();Field OnDependencyInjectionImplementationTypeNameRegularExpression
Regex filter for implementation types in dependency injection hooks. Default:
.+
.// OnDependencyInjectionImplementationTypeNameRegularExpression = Dependency DI.Setup("Composition") .Bind<IDependency>().To<Dependency>();or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition") .Hint(Hint.OnDependencyInjectionImplementationTypeNameRegularExpression, "Dependency") .Bind<IDependency>().To<Dependency>();Field OnDependencyInjectionImplementationTypeNameWildcard
Wildcard filter for implementation types in dependency injection hooks. Default:
*
.// OnDependencyInjectionImplementationTypeNameWildcard = *Dependency DI.Setup("Composition") .Bind<IDependency>().To<Dependency>();or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition") .Hint(Hint.OnDependencyInjectionImplementationTypeNameWildcard, "*Dependency") .Bind<IDependency>().To<Dependency>();Field OnDependencyInjectionContractTypeNameRegularExpression
Regex filter for contract types in dependency injection hooks. Default:
.+
.// OnDependencyInjectionContractTypeNameRegularExpression = IDependency DI.Setup("Composition") .Bind<IDependency>().To<Dependency>();or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition") .Hint(Hint.OnDependencyInjectionContractTypeNameRegularExpression, "IDependency") .Bind<IDependency>().To<Dependency>();Field OnDependencyInjectionContractTypeNameWildcard
Wildcard filter for contract types in dependency injection hooks. Default:
*
.// OnDependencyInjectionContractTypeNameWildcard = *IDependency DI.Setup("Composition") .Bind<IDependency>().To<Dependency>();or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition") .Hint(Hint.OnDependencyInjectionContractTypeNameWildcard, "*IDependency") .Bind<IDependency>().To<Dependency>();Field OnDependencyInjectionTagRegularExpression
Regex filter for tags in dependency injection hooks. Default:
.+
.// OnDependencyInjectionTagRegularExpression = MyTag DI.Setup("Composition") .Bind<IDependency>("MyTag").To<Dependency>();or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition") .Hint(Hint.OnDependencyInjectionTagRegularExpression, "MyTag") .Bind<IDependency>("MyTag").To<Dependency>();Field OnDependencyInjectionTagWildcard
Wildcard filter for tags in dependency injection hooks. Default:
*
.// OnDependencyInjectionTagWildcard = MyTag DI.Setup("Composition") .Bind<IDependency>("MyTag").To<Dependency>();or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition") .Hint(Hint.OnDependencyInjectionTagWildcard, "MyTag") .Bind<IDependency>("MyTag").To<Dependency>();Field OnDependencyInjectionLifetimeRegularExpression
Regex filter for lifetimes in dependency injection hooks. Default:
.+
.// OnDependencyInjectionLifetimeRegularExpression = Singleton DI.Setup("Composition") .Bind<IDependency>().To<Dependency>();or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition") .Hint(Hint.OnDependencyInjectionLifetimeRegularExpression, "Singleton") .Bind<IDependency>().To<Dependency>();Field OnDependencyInjectionLifetimeWildcard
Wildcard filter for lifetimes in dependency injection hooks. Default:
*
.// OnDependencyInjectionLifetimeWildcard = *Singleton DI.Setup("Composition") .Bind<IDependency>().To<Dependency>();or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition") .Hint(Hint.OnDependencyInjectionLifetimeWildcard, "*Singleton") .Bind<IDependency>().To<Dependency>();Field OnCannotResolve
Enables/disables unresolved dependency handlers. Default:
Off
.// OnCannotResolve = On DI.Setup("Composition") .Bind<IDependency>().To<Dependency>();or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition") .Hint(Hint.OnCannotResolve, "On") .Bind<IDependency>().To<Dependency>();Field OnCannotResolvePartial
Enables/disables partial method generation for unresolved dependency handlers. Default:
On
.// OnCannotResolvePartial = On DI.Setup("Composition") .Bind<IDependency>().To<Dependency>();or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition") .Hint(Hint.OnCannotResolvePartial, "On") .Bind<IDependency>().To<Dependency>();Field OnCannotResolveContractTypeNameRegularExpression
Regex filter for contract types in unresolved dependency handlers. Default:
.+
.// OnCannotResolveContractTypeNameRegularExpression = OtherType DI.Setup("Composition") .Bind<IDependency>().To<Dependency>();or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition") .Hint(Hint.OnCannotResolveContractTypeNameRegularExpression, "OtherType") .Bind<IDependency>().To<Dependency>();Field OnCannotResolveContractTypeNameWildcard
Wildcard filter for contract types in unresolved dependency handlers. Default:
*
.// OnCannotResolveContractTypeNameWildcard = *OtherType DI.Setup("Composition") .Bind<IDependency>().To<Dependency>();or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition") .Hint(Hint.OnCannotResolveContractTypeNameWildcard, "*OtherType") .Bind<IDependency>().To<Dependency>();Field OnCannotResolveTagRegularExpression
Regex filter for tags in unresolved dependency handlers. Default:
.+
.// OnCannotResolveTagRegularExpression = MyTag DI.Setup("Composition") .Bind<IDependency>().To<Dependency>();or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition") .Hint(Hint.OnCannotResolveTagRegularExpression, "MyTag") .Bind<IDependency>().To<Dependency>();Field OnCannotResolveTagWildcard
Wildcard filter for tags in unresolved dependency handlers. Default:
*
.// OnCannotResolveTagWildcard = MyTag DI.Setup("Composition") .Bind<IDependency>().To<Dependency>();or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition") .Hint(Hint.OnCannotResolveTagWildcard, "MyTag") .Bind<IDependency>().To<Dependency>();Field OnCannotResolveLifetimeRegularExpression
Regex filter for lifetimes in unresolved dependency handlers. Default:
.+
.// OnCannotResolveLifetimeRegularExpression = Singleton DI.Setup("Composition") .Bind<IDependency>().To<Dependency>();or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition") .Hint(Hint.OnCannotResolveLifetimeRegularExpression, "Singleton") .Bind<IDependency>().To<Dependency>();Field OnCannotResolveLifetimeWildcard
Wildcard filter for lifetimes in unresolved dependency handlers. Default:
*
.// OnCannotResolveLifetimeWildcard = *Singleton DI.Setup("Composition") .Bind<IDependency>().To<Dependency>();or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition") .Hint(Hint.OnCannotResolveLifetimeWildcard, "*Singleton") .Bind<IDependency>().To<Dependency>();Field OnNewRoot
Enables/disables composition root registration event handlers. Default:
Off
.// OnNewRoot = On DI.Setup("Composition") .Bind<IDependency>().To<Dependency>();or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition") .Hint(Hint.OnNewRoot, "On") .Bind<IDependency>().To<Dependency>();Field OnNewRootPartial
Enables/disables partial method generation for composition root events. Default:
Off
.// OnNewRootPartial = On DI.Setup("Composition") .Bind<IDependency>().To<Dependency>();or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition") .Hint(Hint.OnNewRootPartial, "On") .Bind<IDependency>().To<Dependency>();Field ToString
Enables/disables generation of mermaid-format class diagram via ToString(). Default:
Off
.// ToString = On DI.Setup("Composition") .Bind<IDependency>().To<Dependency>();or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition") .Hint(Hint.ToString, "On") .Bind<IDependency>().To<Dependency>();Field ThreadSafe
Enables/disables thread-safe composition object creation. Default:
On
.// ThreadSafe = Off DI.Setup("Composition") .Bind<IDependency>().To<Dependency>();or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition") .Hint(Hint.ThreadSafe, "Off") .Bind<IDependency>().To<Dependency>();Field ResolveMethodModifiers
Modifier override for Resolve() method. Default:
public
.// ResolveMethodModifiers = internal DI.Setup("Composition") .Bind<IDependency>().To<Dependency>();or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition") .Hint(Hint.ResolveMethodModifiers, "internal") .Bind<IDependency>().To<Dependency>();Field ResolveMethodName
Name override for Resolve() method. Default:
Resolve
.// ResolveMethodName = GetService DI.Setup("Composition") .Bind<IDependency>().To<Dependency>();or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition") .Hint(Hint.ResolveMethodName, "GetService") .Bind<IDependency>().To<Dependency>();Field ResolveByTagMethodModifiers
Modifier override for Resolve(tag) method. Default:
public
.// ResolveByTagMethodModifiers = internal DI.Setup("Composition") .Bind<IDependency>().To<Dependency>();or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition") .Hint(Hint.ResolveByTagMethodModifiers, "internal") .Bind<IDependency>().To<Dependency>();Field ResolveByTagMethodName
Name override for Resolve(tag) method. Default:
Resolve
. For example// ResolveByTagMethodName = GetService DI.Setup("Composition") .Bind<IDependency>().To<Dependency>();or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition") .Hint(Hint.ResolveByTagMethodName, "GetService") .Bind<IDependency>().To<Dependency>();Field ObjectResolveMethodModifiers
Modifier override for Resolve(Type) method. Default:
public
.// ObjectResolveMethodModifiers = internal DI.Setup("Composition") .Bind<IDependency>().To<Dependency>();or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition") .Hint(Hint.ObjectResolveMethodModifiers, "internal") .Bind<IDependency>().To<Dependency>();Field ObjectResolveMethodName
Name override for Resolve(Type) method. Default:
Resolve
.// ObjectResolveMethodName = GetService DI.Setup("Composition") .Bind<IDependency>().To<Dependency>();or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition") .Hint(Hint.ObjectResolveMethodName, "GetService") .Bind<IDependency>().To<Dependency>();Field ObjectResolveByTagMethodModifiers
Modifier override for Resolve(Type, tag) method. Default:
public
.// ObjectResolveByTagMethodModifiers = internal DI.Setup("Composition") .Bind<IDependency>().To<Dependency>();or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition") .Hint(Hint.ObjectResolveByTagMethodModifiers, "internal") .Bind<IDependency>().To<Dependency>();Field ObjectResolveByTagMethodName
Name override for Resolve(Type, tag) method. Default:
Resolve
.// ObjectResolveByTagMethodName = GetService DI.Setup("Composition") .Bind<IDependency>().To<Dependency>();or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition") .Hint(Hint.ObjectResolveByTagMethodName, "GetService") .Bind<IDependency>().To<Dependency>();Field DisposeMethodModifiers
Modifier override for Dispose() method. Default:
public
.// DisposeMethodModifiers = internal DI.Setup("Composition") .Bind<IDependency>().To<Dependency>();or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition") .Hint(Hint.DisposeMethodModifiers, "internal") .Bind<IDependency>().To<Dependency>();Field DisposeAsyncMethodModifiers
Modifier override for DisposeAsync() method. Default:
public
.// DisposeAsyncMethodModifiers = internal DI.Setup("Composition") .Bind<IDependency>().To<Dependency>();or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition") .Hint(Hint.DisposeAsyncMethodModifiers, "internal") .Bind<IDependency>().To<Dependency>();Field FormatCode
Enables/disables code formatting (CPU intensive). Default:
Off
.// FormatCode = On DI.Setup("Composition") .Bind<IDependency>().To<Dependency>();or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition") .Hint(Hint.FormatCode, "On") .Bind<IDependency>().To<Dependency>();Field SeverityOfNotImplementedContract
Severity level for unimplemented contract errors. Default:
Error
.// SeverityOfNotImplementedContract = Warning DI.Setup("Composition") .Bind<IDependency>().To<Dependency>();or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition") .Hint(Hint.SeverityOfNotImplementedContract, "Warning") .Bind<IDependency>().To<Dependency>();Field Comments
Enables/disables generated code comments. Default:
On
.// Comments = Off DI.Setup("Composition") .Bind<IDependency>().To<Dependency>();or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition") .Hint(Hint.Comments, "Off") .Bind<IDependency>().To<Dependency>();Field SkipDefaultConstructor
Enables/disables skipping the default constructor. Default:
Off
(meaning the default constructor is used when available).// SkipDefaultConstructor = On DI.Setup("Composition") .Bind<IDependency>().To<Dependency>();or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition") .Hint(Hint.UseDefaultConstructor, "Off") .Bind<IDependency>().To<Dependency>();Field SkipDefaultConstructorImplementationTypeNameRegularExpression
Regex filter for types to skip default constructors. Default:
.+
.// SkipDefaultConstructorImplementationTypeNameRegularExpression = Dependency DI.Setup("Composition") .Bind<IDependency>().To<Dependency>();or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition") .Hint(Hint.SkipDefaultConstructorImplementationTypeNameRegularExpression, "Dependency") .Bind<IDependency>().To<Dependency>();Field SkipDefaultConstructorImplementationTypeNameWildcard
Wildcard filter for types to skip default constructors. Default:
*
.// SkipDefaultConstructorImplementationTypeNameWildcard = *Dependency DI.Setup("Composition") .Bind<IDependency>().To<Dependency>();or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition") .Hint(Hint.SkipDefaultConstructorImplementationTypeNameWildcard, "*Dependency") .Bind<IDependency>().To<Dependency>();Field SkipDefaultConstructorLifetimeRegularExpression
Regex filter for lifetimes to skip default constructors. Default:
.+
.// SkipDefaultConstructorLifetimeRegularExpression = Singleton DI.Setup("Composition") .Bind<IDependency>().To<Dependency>();or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition") .Hint(Hint.SkipDefaultConstructorLifetimeRegularExpression, "Singleton") .Bind<IDependency>().To<Dependency>();Field SkipDefaultConstructorLifetimeWildcard
Wildcard filter for lifetimes to skip default constructors. Default:
*
.// SkipDefaultConstructorLifetimeWildcard = *Singleton DI.Setup("Composition") .Bind<IDependency>().To<Dependency>();or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition") .Hint(Hint.SkipDefaultConstructorLifetimeWildcard, "*Singleton") .Bind<IDependency>().To<Dependency>();Field DisableAutoBinding
Disables automatic binding when no explicit binding exists. Default:
Off
.// DisableAutoBinding = On DI.Setup("Composition") .Bind<IDependency>().To<Dependency>();or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition") .Hint(Hint.DisableAutoBinding, "Off") .Bind<IDependency>().To<Dependency>();Field DisableAutoBindingImplementationTypeNameRegularExpression
Regex filter for implementation types to disable auto-binding. Default:
.+
.// DisableAutoBindingImplementationTypeNameRegularExpression = Dependency DI.Setup("Composition") .Hint(Hint.DisableAutoBinding, "Off") .Bind<IDependency>().To<Dependency>();or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition") .Hint(Hint.DisableAutoBinding, "Off") .Hint(Hint.DisableAutoBindingImplementationTypeNameRegularExpression, "Dependency") .Bind<IDependency>().To<Dependency>();Field DisableAutoBindingImplementationTypeNameWildcard
Wildcard filter for implementation types to disable auto-binding. Default:
*
.// DisableAutoBindingImplementationTypeNameWildcard = *Dependency DI.Setup("Composition") .Hint(Hint.DisableAutoBinding, "Off") .Bind<IDependency>().To<Dependency>();or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition") .Hint(Hint.DisableAutoBinding, "Off") .Hint(Hint.DisableAutoBindingImplementationTypeNameWildcard, "*Dependency") .Bind<IDependency>().To<Dependency>();Field DisableAutoBindingLifetimeRegularExpression
Regex filter for lifetimes to disable auto-binding. Default:
.+
.// DisableAutoBindingLifetimeRegularExpression = Singleton DI.Setup("Composition") .Hint(Hint.DisableAutoBinding, "Off") .Bind<IDependency>().To<Dependency>();or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition") .Hint(Hint.DisableAutoBinding, "Off") .Hint(Hint.DisableAutoBindingLifetimeRegularExpression, "Singleton") .Bind<IDependency>().To<Dependency>();Field DisableAutoBindingLifetimeWildcard
Wildcard filter for lifetimes to disable auto-binding. Default:
*
.// DisableAutoBindingLifetimeWildcard = *Singleton DI.Setup("Composition") .Hint(Hint.DisableAutoBinding, "Off") .Bind<IDependency>().To<Dependency>();or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition") .Hint(Hint.DisableAutoBinding, "Off") .Hint(Hint.DisableAutoBindingLifetimeWildcard, "*Singleton") .Bind<IDependency>().To<Dependency>();IBinding
Defines the API for configuring dependency bindings in the composition.
Method Bind(System.Object[])
Starts binding definition for the implementation type itself. Also binds all directly implemented abstract types excluding special system interfaces. Special system interfaces are excluded from binding: System.ObjectSystem.EnumSystem.MulticastDelegateSystem.DelegateSystem.Collections.IEnumerableSystem.Collections.Generic.IEnumerableSystem.Collections.Generic.IistSystem.Collections.Generic.ICollectionSystem.Collections.IEnumeratorSystem.Collections.Generic.IEnumeratorSystem.Collections.Generic.IIReadOnlyListSystem.Collections.Generic.IReadOnlyCollectionSystem.IDisposableSystem.IAsyncResultSystem.AsyncCallback
DI.Setup("Composition") .Bind().To<Service>();
parameter tags - Optional tags to associate with this binding.
returns Binding configuration interface for method chaining.
See also To``1.
See also To
1(System.Func{Pure.DI.IContext,
0}).See also !:To<T1,T>().
See also !:To<T1,T2,T>().
See also Tags(System.Object[]).
See also As(Pure.DI.Lifetime).
Method Bind``1(System.Object[])
Starts binding definition for a specific dependency type.
DI.Setup("Composition") .Bind<IDependency>().To<Dependency>();Dependency type to bind. Supports type markers like TT and TTList`1.
parameter tags - Optional tags to associate with this binding.
returns Binding configuration interface for method chaining.
See also To``1.
See also To
1(System.Func{Pure.DI.IContext,
0}).See also !:To<T1,T>().
See also !:To<T1,T2,T>().
See also Tags(System.Object[]).
See also As(Pure.DI.Lifetime).
Method Bind``2(System.Object[])
Starts binding definition for multiple dependency types simultaneously. See Bind``1(System.Object[]) for detailed usage. First dependency type to bind.Second dependency type to bind.
parameter tags - Optional tags to associate with these bindings.
returns Binding configuration interface for method chaining.
See also To``1.
See also To
1(System.Func{Pure.DI.IContext,
0}).See also !:To<T1,T>().
See also !:To<T1,T2,T>().
See also Tags(System.Object[]).
See also As(Pure.DI.Lifetime).
Method Bind``3(System.Object[])
Starts binding definition for multiple dependency types simultaneously. See Bind``1(System.Object[]) for detailed usage. First dependency type to bind.Second dependency type to bind.Third dependency type to bind.
parameter tags - Optional tags to associate with these bindings.
returns Binding configuration interface for method chaining.
See also To``1.
See also To
1(System.Func{Pure.DI.IContext,
0}).See also !:To<T1,T>().
See also !:To<T1,T2,T>().
See also Tags(System.Object[]).
See also As(Pure.DI.Lifetime).
Method Bind``4(System.Object[])
Starts binding definition for multiple dependency types simultaneously. See Bind``1(System.Object[]) for detailed usage. First dependency type to bind.Second dependency type to bind.Third dependency type to bind.Fourth dependency type to bind.
parameter tags - Optional tags to associate with these bindings.
returns Binding configuration interface for method chaining.
See also To``1.
See also To
1(System.Func{Pure.DI.IContext,
0}).See also !:To<T1,T>().
See also !:To<T1,T2,T>().
See also Tags(System.Object[]).
See also As(Pure.DI.Lifetime).
Method As(Pure.DI.Lifetime)
Specifies the lifetime scope for the binding.
DI.Setup("Composition") .Bind<IDependency>().As(Lifetime.Singleton).To<Dependency>();
parameter lifetime - Lifetime scope for the binding.
returns Binding configuration interface for method chaining.
See also Bind``1(System.Object[]).
See also To``1.
See also To
1(System.Func{Pure.DI.IContext,
0}).See also !:To<T1,T>().
See also !:To<T1,T2,T>().
See also Tags(System.Object[]).
Method Tags(System.Object[])
Specifies binding tags to differentiate between multiple implementations of the same interface.
interface IDependency { } class AbcDependency: IDependency { } class XyzDependency: IDependency { } class Dependency: IDependency { } interface IService { IDependency Dependency1 { get; } IDependency Dependency2 { get; } } class Service: IService { public Service( [Tag("Abc")] IDependency dependency1, [Tag("Xyz")] IDependency dependency2) { Dependency1 = dependency1; Dependency2 = dependency2; } public IDependency Dependency1 { get; } public IDependency Dependency2 { get; } } DI.Setup("Composition") .Bind<IDependency>().Tags("Abc").To<AbcDependency>() .Bind<IDependency>().Tags("Xyz").To<XyzDependency>() .Bind<IService>().To<Service>().Root<IService>("Root");
parameter tags - Tags to associate with this binding.
returns Binding configuration interface for method chaining.
See also Bind``1(System.Object[]).
See also To``1.
See also To
1(System.Func{Pure.DI.IContext,
0}).See also !:To<T1,T>().
See also !:To<T1,T2,T>().
See also As(Pure.DI.Lifetime).
Method To``1
Specifies the implementation type for the binding.
DI.Setup("Composition") .Bind<IDependency>().To<Dependency>();Implementation type. Supports generic type markers.
- returns Configuration interface for method chaining.
See also Bind``1(System.Object[]).
See also To
1(System.Func{Pure.DI.IContext,
0}).See also !:To<T1,T>().
See also !:To<T1,T2,T>().
See also Tags(System.Object[]).
See also As(Pure.DI.Lifetime).
Method To``1(System.Func{Pure.DI.IContext,``0})
Specifies a factory method to create the implementation instance.
DI.Setup("Composition") .Bind<IService>() To(_ => { var service = new Service("My Service"); service.Initialize(); return service; }) // Another example: DI.Setup("Composition") .Bind<IService>() To(ctx => { ctx.Inject<IDependency>(out var dependency); return new Service(dependency); }) // And another example: DI.Setup("Composition") .Bind<IService>() To(ctx => { // Builds up an instance with all necessary dependencies ctx.Inject<Service>(out var service); service.Initialize(); return service; })
- parameter factory - Factory method to create and initialize the instance. Implementation type.
- returns Configuration interface for method chaining.
See also Bind``1(System.Object[]).
See also To``1.
See also !:To<T1,T>().
See also !:To<T1,T2,T>().
See also Tags(System.Object[]).
See also As(Pure.DI.Lifetime). This method is useful for creating and initializing an instance manually. At the compilation stage, the set of dependencies that the object to be created needs is determined. In most cases, this happens automatically, according to the set of constructors and their arguments, and does not require additional customization efforts. But sometimes it is necessary to manually create and/or initialize an object. There are scenarios where manual control over the creation process is required, such as when additional initialization logic is neededwhen complex construction steps are requiredwhen specific object states need to be set during creation
Method To``1(System.String)
Specifies a source code statement to create the implementation.
DI.Setup("Composition") .Bind<int>().To<int>("dependencyId") .Bind<Func<int, IDependency>>() .To<Func<int, IDependency>>(ctx => dependencyId => { ctx.Inject<Dependency>(out var dependency); return dependency; });
- parameter sourceCodeStatement - Source code expression to create the instance. Implementation type.
- returns Configuration interface for method chaining.
See also Bind``1(System.Object[]).
Method To``2(System.Func{``0,``1})
Specifies a simplified factory method with dependency parameters.
DI.Setup(nameof(Composition)) .Bind<IDependency>().To(( Dependency dependency) => { dependency.Initialize(); return dependency; }); // Variant using TagAttribute: DI.Setup(nameof(Composition)) .Bind<IDependency>().To(( [Tag("some tag")] Dependency dependency) => { dependency.Initialize(); return dependency; });
- parameter factory - Factory method with injected dependencies. Type of the first dependency parameter.Implementation type.
- returns Configuration interface for method chaining.
See also Bind``1(System.Object[]).
See also To
1(System.Func{Pure.DI.IContext,
0}).See also To``1.
See also Tags(System.Object[]).
See also As(Pure.DI.Lifetime).
Method To``3(System.Func{``0,``1,``2})
Specifies a simplified factory method with multiple dependency parameters.
DI.Setup(nameof(Composition)) .Bind<IDependency>().To(( Dependency dependency, DateTimeOffset time) => { dependency.Initialize(time); return dependency; }); // Variant using TagAttribute: DI.Setup(nameof(Composition)) .Bind("now datetime").To(_ => DateTimeOffset.Now) .Bind<IDependency>().To(( Dependency dependency, [Tag("now datetime")] DateTimeOffset time) => { dependency.Initialize(time); return dependency; });
- parameter factory - Factory method with injected dependencies. Type of the first dependency parameter.Type of second dependency parameter.Implementation type.
- returns Configuration interface for method chaining.
See also Bind``1(System.Object[]).
See also To
1(System.Func{Pure.DI.IContext,
0}).See also To``1.
See also Tags(System.Object[]).
See also As(Pure.DI.Lifetime).
Method To``4(System.Func{``0,``1,``2,``3})
Specifies a simplified factory method with multiple dependency parameters.
- parameter factory - Factory method with injected dependencies. Type of the first dependency parameter.Type of the second dependency parameter.Type of the third dependency parameter.Implementation type.
- returns Configuration interface for method chaining.
See also Bind``1(System.Object[]).
See also To
1(System.Func{Pure.DI.IContext,
0}).See also To``1.
See also Tags(System.Object[]).
See also As(Pure.DI.Lifetime).
IConfiguration
Defines an API for configuring Dependency Injection bindings.
See also Setup(System.String,Pure.DI.CompositionKind).
Method Bind(System.Object[])
Starts binding definition for the implementation type itself. Also binds all directly implemented abstract types excluding special system interfaces. Special system interfaces are excluded from binding: System.ObjectSystem.EnumSystem.MulticastDelegateSystem.DelegateSystem.Collections.IEnumerableSystem.Collections.Generic.IEnumerableSystem.Collections.Generic.IListSystem.Collections.Generic.ICollectionSystem.Collections.IEnumeratorSystem.Collections.Generic.IEnumeratorSystem.Collections.Generic.IIReadOnlyListSystem.Collections.Generic.IReadOnlyCollectionSystem.IDisposableSystem.IAsyncResultSystem.AsyncCallback
DI.Setup("Composition") .Bind().To<Service>();
parameter tags - Optional tags to associate with the binding.
returns Binding configuration interface for method chaining.
See also To``1.
See also To
1(System.Func{Pure.DI.IContext,
0}).See also To<T1,T>().
See also To<T1,T2,T>().
See also Tags(System.Object[]).
See also As(Pure.DI.Lifetime).
Method Bind``1(System.Object[])
Starts binding definition for a specific dependency type.
DI.Setup("Composition") .Bind<IService>().To<Service>();Dependency type to bind.
parameter tags - Optional tags to associate with the binding.
returns Binding configuration interface for method chaining.
See also To``1.
See also To
1(System.Func{Pure.DI.IContext,
0}).See also To<T1,T>().
See also To<T1,T2,T>().
See also Tags(System.Object[]).
See also As(Pure.DI.Lifetime).
Method Bind``2(System.Object[])
Starts binding definition for multiple dependency types simultaneously. See Bind``1(System.Object[]) for detailed usage. First dependency type to bind.Second dependency type to bind.
parameter tags - Optional tags to associate with the binding.
returns Binding configuration interface for method chaining.
See also To``1.
See also To
1(System.Func{Pure.DI.IContext,
0}).See also To<T1,T>().
See also To<T1,T2,T>().
See also Tags(System.Object[]).
seealso cref="IBinding.As"/>
Method Bind``3(System.Object[])
Starts binding definition for multiple dependency types simultaneously. See Bind``1(System.Object[]) for detailed usage. First dependency type to bind.Second dependency type to bind.Third dependency type to bind.
parameter tags - Optional tags to associate with the binding.
returns Binding configuration interface for method chaining.
See also To``1.
See also To
1(System.Func{Pure.DI.IContext,
0}).See also To<T1,T>().
See also To<T1,T2,T>().
See also Tags(System.Object[]).
See also As(Pure.DI.Lifetime).
Method Bind``4(System.Object[])
Starts binding definition for multiple dependency types simultaneously. See Bind``1(System.Object[]) for detailed usage. First dependency type to bind.Second dependency type to bind.Third dependency type to bind.Fourth dependency type to bind.
parameter tags - Optional tags to associate with the binding.
returns Binding configuration interface for method chaining.
See also To``1.
See also To
1(System.Func{Pure.DI.IContext,
0}).See also To<T1,T>().
See also To<T1,T2,T>().
See also Tags(System.Object[]).
See also As(Pure.DI.Lifetime).
Method RootBind``1(System.String,Pure.DI.RootKinds,System.Object[])
Starts binding definition with automatic root creation for a dependency type.
DI.Setup("Composition") .RootBind<IService>();Dependency type to bind and expose as root.
parameter name - Root name template (supports {type}, {TYPE}, {tag} placeholders). Empty name creates a private root accessible only via Resolve methods.
parameter kind - Specifies root accessibility and creation method.
parameter tags - Tags for binding (first tag used for {tag} placeholder).
returns Binding configuration interface for method chaining.
See also To``1.
See also To
1(System.Func{Pure.DI.IContext,
0}).See also To<T1,T>().
See also To<T1,T2,T>().
See also Tags(System.Object[]).
See also As(Pure.DI.Lifetime).
Method DependsOn(System.String[])
Specifies base setups to inherit bindings from.
DI.Setup("Composition") .DependsOn(nameof(CompositionBase));
parameter setupNames - Names of base composition setups.
returns Configuration interface for method chaining.
See also Setup(System.String,Pure.DI.CompositionKind).
Method GenericTypeArgumentAttribute``1
Registers custom generic type markers.
[AttributeUsage(AttributeTargets.Interface | AttributeTargets.Class | AttributeTargets.Struct)] class MyGenericTypeArgumentAttribute: Attribute; [MyGenericTypeArgument] interface TTMy; DI.Setup("Composition") .GenericTypeAttribute<MyGenericTypeArgumentAttribute>() .Bind<IDependency<TTMy>>().To<Dependency<TTMy>>();Custom attribute type.
- returns Configuration interface for method chaining.
See also GenericTypeArgumentAttribute``1.
Method TypeAttribute``1(System.Int32)
Registers a custom attribute to override injection types.
DI.Setup("Composition") .TypeAttribute<MyTypeAttribute>();
- parameter typeArgumentPosition - Position of type parameter in attribute constructor (default: 0). Custom attribute type.
- returns Configuration interface for method chaining.
See also TypeAttribute.
Method TagAttribute``1(System.Int32)
Registers a custom attribute to override injection tags.
DI.Setup("Composition") .TagAttribute<MyTagAttribute>();
- parameter tagArgumentPosition - Position of tag parameter in attribute constructor (default: 0). Custom attribute type.
- returns Configuration interface for method chaining.
See also TagAttribute.
Method OrdinalAttribute``1(System.Int32)
Registers a custom attribute to override injection priority.
DI.Setup("Composition") .OrdinalAttribute<MyOrdinalAttribute>();
- parameter ordinalArgumentPosition - Position of ordinal parameter in attribute constructor (default: 0). Custom attribute type.
- returns Configuration interface for method chaining.
See also OrdinalAttribute.
Method DefaultLifetime(Pure.DI.Lifetime)
Sets the default lifetime for the following bindings.
DI.Setup("Composition") .DefaultLifetime(Lifetime.Singleton);
parameter lifetime - Default lifetime to apply.
returns Configuration interface for method chaining.
See also Lifetime.
See also As(Pure.DI.Lifetime).
Method DefaultLifetime``1(Pure.DI.Lifetime,System.Object[])
Sets the default lifetime for bindings of specific types for the following bindings.
DI.Setup("Composition") .DefaultLifetime<IMySingleton>(Lifetime.Singleton);DI.Setup("Composition") .DefaultLifetime<IMySingleton>(Lifetime.Singleton, "my tag");
parameter lifetime - Default lifetime to apply.
parameter tags - Tags specifying which bindings to apply this lifetime to. Type filter for applicable bindings.
returns Configuration interface for method chaining.
See also Lifetime.
See also As(Pure.DI.Lifetime).
Method Arg``1(System.String,System.Object[])
Adds a composition argument to be injected.
DI.Setup("Composition") .Arg<int>("id");Argument type.
parameter name - Argument name template (supports {type}, {TYPE}, {tag} placeholders).
parameter tags - Tags to associate with the argument.
returns Configuration interface for method chaining.
See also RootArg``1(System.String,System.Object[]).
Method RootArg``1(System.String,System.Object[])
Adds a root argument to be injected.
DI.Setup("Composition") .RootArg<int>("id");Argument type.
parameter name - Argument name template (supports {type}, {TYPE}, {tag} placeholders).
parameter tags - Tags to associate with the argument.
returns Configuration interface for method chaining.
See also Arg``1(System.String,System.Object[]).
Method Root``1(System.String,System.Object,Pure.DI.RootKinds)
Defines the composition root.
DI.Setup("Composition") .Root<Service>("MyService");DI.Setup("Composition") .Root<Service>("My{type}");Root type to expose.
parameter name - Root name template (supports {type}, {TYPE}, {tag} placeholders). Empty name creates the private root accessible only via
Resolve
methods.parameter tag - Tag to associate with the root.
parameter kind - Specifies root accessibility and creation method.
returns Configuration interface for method chaining.
See also RootBind``1(System.String,Pure.DI.RootKinds,System.Object[]).
See also Roots``1(System.String,Pure.DI.RootKinds,System.String).
Method Roots``1(System.String,Pure.DI.RootKinds,System.String)
Automatically creates roots for all base type implementations found at the time the method is called.
DI.Setup("Composition") .Roots<IService>();DI.Setup("Composition") .Roots<IService>("Root{type}", filter: "*MyService");Base type for auto-root discovery.
parameter name - Root name template (supports {type}, {TYPE} placeholders). Empty name creates private roots accessible only via Resolve methods.
parameter kind - Specifies root accessibility and creation method.
parameter filter - Wildcard pattern to filter types by full name.
returns Configuration interface for method chaining.
See also Root``1(System.String,System.Object,Pure.DI.RootKinds).
Method Builder``1(System.String,Pure.DI.RootKinds)
Defines a builder method for initializing instances post-creation.
DI.Setup("Composition") .Builder<Service>("BuildUpMyService");Type the builder method applies to.
parameter name - Builder method name template (supports {type}, {TYPE} placeholders). Default: "BuildUp".
parameter kind - Specifies builder accessibility.
returns Configuration interface for method chaining.
See also Builders``1(System.String,Pure.DI.RootKinds,System.String).
Method Builders``1(System.String,Pure.DI.RootKinds,System.String)
Automatically creates builders for all discoverable implementations of a base type found at the time the method is called.
DI.Setup("Composition") .Builders<Service>();DI.Setup("Composition") .Builder<Service>("BuildUp");DI.Setup("Composition") .Builder<Service>("BuildUp{type}", filter: "*MyService");Base type for builder discovery.
parameter name - Builder method name template (supports {type}, {TYPE} placeholders). Default: "BuildUp".
parameter kind - Specifies builder accessibility.
parameter filter - Wildcard pattern to filter types by full name.
returns Configuration interface for method chaining.
See also Builder``1(System.String,Pure.DI.RootKinds).
Method Hint(Pure.DI.Hint,System.String)
Configures code generation options.
DI.Setup("Composition") .Hint(Resolve, "Off");
parameter hint - Hint type to configure.
parameter value - Value to set for the hint.
returns Configuration interface for method chaining.
See also Hint.
Method Accumulate``2(Pure.DI.Lifetime[])
Registers an accumulator for collecting instances of specific lifetimes. If no lifetime is specified, it works for all.
DI.Setup("Composition") .Accumulate<IDisposable, MyAccumulator>(Lifetime.Transient);
parameter lifetimes - Lifetimes of instances to accumulate. Type of instances to collect.Accumulator type (requires parameterless constructor and Add(T) method).
returns Configuration interface for method chaining.
See also Lifetime.
Method GenericTypeArgument``1
Defines a generic type marker for generic bindings.
interface TTMy; DI.Setup("Composition") .GenericTypeArgument<TTMy>() .Bind<IDependency<TTMy>>().To<Dependency<TTMy>>();Generic type marker.
- returns Configuration interface for method chaining.
See also GenericTypeArgumentAttribute``1.
IContext
Injection context. Cannot be used outside the binding setup.
Property Tag
The tag that was used to inject the current object in the object graph. Cannot be used outside the binding setup. See also Tags(System.Object[])
DI.Setup("Composition") .Bind<Lazy<TT>>() .To(ctx => { ctx.Inject<Func<TT>>(ctx.Tag, out var func); return new Lazy<TT>(func, false); };See also To
1(System.Func{Pure.DI.IContext,
0}).See also Tags(System.Object[]).
Property ConsumerTypes
The chain of consumer types for which an instance is created, from the immediate consumer down to the composition type. Cannot be used outside the binding setup. Guaranteed to contain at least one element.
var box = new Composition().Box; // Output: ShroedingersCat, CardboardBox`1, Composition static void Setup() => DI.Setup(nameof(Composition)) .Bind().To(ctx => new Log(ctx.ConsumerTypes)) .Bind().To<ShroedingersCat>() .Bind().To<CardboardBox<TT>>() .Root<CardboardBox<ShroedingersCat>>("Box"); public class Log { public Log(Type[] types) => Console.WriteLine(string.Join(", ", types.Select(type => type.Name))); } public record CardboardBox<T>(T Content); public record ShroedingersCat(Log log);See also ConsumerType.
See also To
1(System.Func{Pure.DI.IContext,
0}).Property ConsumerType
The immediate consumer type for which the instance is created. Cannot be used outside the binding setup.
var box = new Composition().Box; // Output: ShroedingersCat static void Setup() => DI.Setup(nameof(Composition)) .Bind().To(ctx => new Log(ctx.ConsumerType)) .Bind().To<ShroedingersCat>() .Bind().To<CardboardBox<TT>>() .Root<CardboardBox<ShroedingersCat>>("Box"); public class Log { public Log(Type type) => Console.WriteLine(type.Name); } public record CardboardBox<T>(T Content); public record ShroedingersCat(Log log);See also ConsumerTypes.
See also To
1(System.Func{Pure.DI.IContext,
0}).Property Lock
Gets the synchronization object used to control thread-safe access during composition. Used to prevent race conditions during dependency resolution and override operations.
DI.Setup(nameof(Composition)) .Bind<IDependency>().To<IDependency>(ctx => { lock (ctx.Lock) { ctx.Inject(out Dependency dependency); dependency.Initialize(); return dependency; } })Method Inject``1(``0@)
Injects an instance of type
T
. Cannot be used outside the binding setup.DI.Setup("Composition") .Bind<IService>() To(ctx => { ctx.Inject<IDependency>(out var dependency); return new Service(dependency); })and another example:
DI.Setup("Composition") .Bind<IService>() To(ctx => { // Builds up an instance with all necessary dependencies ctx.Inject<Service>(out var service); service.Initialize(); return service; })
- parameter value - Injectable instance. . Instance type. See also To
1(System.Func{Pure.DI.IContext,
0}).Method Inject``1(System.Object,``0@)
Injects an instance of type
T
marked with a tag. Cannot be used outside the binding setup.DI.Setup("Composition") .Bind<IService>() To(ctx => { ctx.Inject<IDependency>("MyTag", out var dependency); return new Service(dependency); })
parameter tag - The injection tag. See also Tags(System.Object[]) .
parameter value - Injectable instance. . Instance type. See also To
1(System.Func{Pure.DI.IContext,
0}).Method BuildUp``1(``0)
Builds up of an existing object. In other words, injects the necessary dependencies via methods, properties, or fields into an existing object. Cannot be used outside the binding setup.
DI.Setup("Composition") .Bind<IService>() To(ctx => { var service = new Service(); // Initialize an instance with all necessary dependencies ctx.BuildUp(service); return service; })
- parameter value - An existing object for which the injection(s) is to be performed. Object type. See also To
1(System.Func{Pure.DI.IContext,
0}).Method Override``1(``0,System.Object[])
Overrides the binding with the specified value. Cannot be used outside the binding setup.
DI.Setup("Composition") .Bind().To<Func<int, int, IDependency>>(ctx => (dependencyId, subId) => { // Overrides with a lambda argument ctx.Override(dependencyId); // Overrides with tag using lambda argument ctx.Override(subId, "sub"); // Overrides with some value ctx.Override($"Dep {dependencyId} {subId}"); // Overrides with injected value ctx.Inject(Tag.Red, out Color red); ctx.Override(red); ctx.Inject<Dependency>(out var dependency); return dependency; })Overrides uses a shared state to override values. And if this code is supposed to run in multiple threads at once, then you need to ensure their synchronization, for example
DI.Setup("Composition") .Bind().To<Func<int, int, IDependency>>(ctx => (dependencyId, subId) => { lock (ctx.Lock) { // Overrides with a lambda argument ctx.Override(dependencyId); // Overrides with tag using lambda argument ctx.Override(subId, "sub"); // Overrides with some value ctx.Override($"Dep {dependencyId} {subId}"); // Overrides with injected value ctx.Inject(Tag.Red, out Color red); ctx.Override(red); ctx.Inject<Dependency>(out var dependency); return dependency; } })An alternative to synchronizing thread yourself is to use types like _Func`3_this. There, threads synchronization is performed automatically.
- parameter value - The object that will be used to override a binding. Object type that will be used to override a binding.
- parameter tags - Injection tags that will be used to override a binding. See also Tags(System.Object[]) .
See also To(System.Func<TArg1,T>).
IOwned
Represents an owned resource whose lifetime is managed by its owner. Provides both synchronous and asynchronous disposal capabilities for proper resource cleanup.
See also Owned.
See also Accumulate``2(Pure.DI.Lifetime[]).
Lifetime
Defines binding lifetimes for dependencies. Binding as Singleton:
DI.Setup("Composition") .Bind<IDependency>().As(Lifetime.Singleton).To<Dependency>();See also Setup(System.String,Pure.DI.CompositionKind).
See also As(Pure.DI.Lifetime).
See also DefaultLifetime(Pure.DI.Lifetime).
See also DefaultLifetime``1(Pure.DI.Lifetime,System.Object[]).
Field Transient
Creates a new dependency instance for each injection (default behavior). Default behavior can be changed by DefaultLifetime(Pure.DI.Lifetime) and DefaultLifetime``1(Pure.DI.Lifetime,System.Object[]). Explicit transient binding:
DI.Setup("Composition") .Bind<IDependency>().As(Lifetime.Transient).To<Dependency>();Default behavior (equivalent):
DI.Setup("Composition") .Bind<IDependency>().To<Dependency>();See also DefaultLifetime(Pure.DI.Lifetime).
See also DefaultLifetime``1(Pure.DI.Lifetime,System.Object[]).
Field Singleton
Maintains a single instance per composition. Singleton binding:
DI.Setup("Composition") .Bind<IService>().As(Lifetime.Singleton).To<Service>();Field PerResolve
Single instance per composition root. Per-resolve binding:
DI.Setup("Composition") .Bind<IProcessor>().As(Lifetime.PerResolve).To<Processor>();Field PerBlock
Reuses instances within code blocks to reduce allocations. Per-block binding:
DI.Setup("Composition") .Bind<ILogger>().As(Lifetime.PerBlock).To<Logger>();Field Scoped
Single instance per dependency scope. Scoped binding:
DI.Setup("Composition") .Bind<IDatabase>().As(Lifetime.Scoped).To<Database>();Name
Provides well-known names used throughout the dependency injection configuration. These names serve as standardized identifiers for common DI components and behaviors.
OrdinalAttribute
Specifies injection order priority for constructors, methods, properties, and fields. While this attribute is part of the DI API, you can implement custom ordering attributes in any namespace. For constructors, it defines the sequence of attempts to use a particular constructor to create an object:
class Service: IService { private readonly string _name; [Ordinal(1)] public Service(IDependency dependency) => _name = "with dependency"; [Ordinal(0)] public Service(string name) => _name = name; }For fields, properties and methods, it specifies to perform dependency injection and defines the sequence:
class Person: IPerson { private readonly string _name = ""; [Ordinal(0)] public int Id; [Ordinal(1)] public string FirstName { set { _name = value; } } public IDependency? Dependency { get; private set; } [Ordinal(2)] public void SetDependency(IDependency dependency) => Dependency = dependency; }See also DependencyAttribute.
See also TagAttribute.
See also TypeAttribute.
Constructor OrdinalAttribute(System.Int32)
Initializes an attribute instance with the specified injection priority.
- parameter ordinal - Lower values indicate higher priority (0 executes before 1). Default: 0.
Owned
Manages lifetime of disposable objects by accumulating them and providing deterministic disposal. Implements both synchronous and asynchronous disposal patterns for comprehensive resource cleanup.
See also IOwned.
See also Accumulate``2(Pure.DI.Lifetime[]).
Method Dispose
Owned`1
Represents an owned resource of type that combines a value with its disposal mechanism. Provides deterministic lifetime management through both synchronous and asynchronous disposal patterns. The type of the owned value. See also IOwned.
See also Owned.
See also Accumulate``2(Pure.DI.Lifetime[]).
Field Value
The owned value instance.
Constructor Owned`1(`0,Pure.DI.IOwned)
Initializes a new owned value with its associated disposal mechanism.
parameter value - The value to be owned and managed.
parameter owned - The disposal mechanism responsible for cleaning up the owned value.
Method Dispose
Pair`1
For internal use.
RootKinds
Specifies configuration flags for composition root members, controlling their access level, modifiers, and representation. Flags can be combined to define complex root behaviors.
See also Root``1(System.String,System.Object,Pure.DI.RootKinds).
See also RootBind``1(System.String,Pure.DI.RootKinds,System.Object[]).
See also Roots``1(System.String,Pure.DI.RootKinds,System.String).
See also Builder``1(System.String,Pure.DI.RootKinds).
See also Builders``1(System.String,Pure.DI.RootKinds,System.String).
Field Default
Default configuration: Public access modifier and property representation.
Field Public
Public access modifier for the composition root.
Field Internal
Internal access modifier for the composition root.
Field Private
Private access modifier for the composition root.
Field Property
Represents the composition root as a property.
Field Method
Represents the composition root as a method.
Field Static
Defines the composition root as static.
Field Partial
Defines the composition root as partial.
Field Exposed
Exposes the root for external binding via attributes.
See also BindAttribute.
Field Protected
Protected access modifier for the composition root.
Field Virtual
Applies virtual modifier to enable overriding in derived classes.
Field Override
Applies override modifier to redefine a base implementation.
Tag
Provides standardized tags for dependency binding scenarios, including special tags for unique bindings, type-based identification, and injection targeting.
See also Bind``1(System.Object[]).
See also Tags(System.Object[]).
Field Unique
Enables multiple distinct bindings for the same instance type. Used for collection injection.
DI.Setup("Composition") .Bind<IService>(Tag.Unique).To<Service1>() .Bind<IService>(Tag.Unique).To<Service1>() .Root<IEnumerable<IService>>("Root");Field Type
Tags bindings by their implementation type for explicit injection.
DI.Setup("Composition") .Bind<IService>(Tag.Type).To<Service>() .Root<IService>("Root", typeof(Service));Field Any
Matches any tag during resolution. Used for conditional bindings that accept any tag.
DI.Setup("Composition") DI.Setup(nameof(Composition)) .Bind<IDependency>(Tag.Any).To(ctx => new Dependency(ctx.Tag)) .Bind<IService>().To<Service>()Method On(System.String[])
Creates a tag targeting specific injection sites using member identifiers.
DI.Setup("Composition") .Bind(Tag.On("MyNamespace.Service.Service:dep")) .To<Dependency>() .Bind().To<Service>() .Root<<IService>("Root");
- parameter injectionSites - Member identifiers in format: [namespace].[type].[member][:argument]. Case-sensitive. Wildcards (*, ?) supported. Omit 'global::'.
Method OnConstructorArg``1(System.String)
Creates a tag targeting a specific constructor parameter by name.
DI.Setup("Composition") .Bind(Tag.OnConstructorArg<Service>("dep")) .To<Dependency>() .Bind().To<Service>() .Root<IService>("Root");
- parameter argName - Constructor parameter name
Method OnMember``1(System.String)
Creates a tag targeting a specific field or property by name.
DI.Setup("Composition") .Bind(Tag.OnMember<Service>("DepProperty")) .To<Dependency>() .Bind().To<Service>() .Root<IService>("Root");
- parameter memberName - Field or property name
Method OnMethodArg``1(System.String,System.String)
Creates a tag targeting a specific method parameter by method and argument names.
DI.Setup("Composition") .Bind(Tag.OnMethodArg<Service>("DoSomething", "state")) .To<Dependency>() .Bind().To<Service>() .Root<IService>("Root");
parameter methodName - Method name
parameter argName - Parameter name
Field VarName
Atomically generated smart tag with value "VarName". It's used for:
class _Generator__VarsMap_ <-- _IIdGenerator_(VarName) -- _IdGenerator_ as _Transient_
Field UsingDeclarations
Atomically generated smart tag with value "UsingDeclarations". It's used for:
class _Generator__CompositionClassBuilder_ <-- _IBuilder{TData, T}_(UsingDeclarations) -- _UsingDeclarationsBuilder_ as _PerBlock_
Field Overrider
Atomically generated smart tag with value "Overrider". It's used for:
class _Generator__DependencyGraphBuilder_ <-- _IGraphRewriter_(Overrider) -- _GraphOverrider_ as _PerBlock_
Field CompositionClass
Atomically generated smart tag with value "CompositionClass". It's used for:
class _Generator__CodeBuilder_ <-- _IBuilder{TData, T}_(CompositionClass) -- _CompositionClassBuilder_ as _PerBlock_
Field UniqueTag
Atomically generated smart tag with value "UniqueTag". It's used for:
class _Generator__ApiInvocationProcessor_ <-- (UniqueTag) -- _IdGenerator_ as _PerResolve__BindingBuilder_ <-- _IIdGenerator_(UniqueTag) -- _IdGenerator_ as _PerResolve_
Field Cleaner
Atomically generated smart tag with value "Cleaner". It's used for:
class _Generator__DependencyGraphBuilder_ <-- _IGraphRewriter_(Cleaner) -- _GraphCleaner_ as _PerBlock_
Field Override
Atomically generated smart tag with value "Override". It's used for:
class _Generator__OverrideIdProvider_ <-- _IIdGenerator_(Override) -- _IdGenerator_ as _PerResolve_
TagAttribute
Represents a tag attribute overriding an injection tag. The tag can be a constant, a type, or a value of an enumerated type. This attribute is part of the API, but you can use your own attribute at any time, and this allows you to define them in the assembly and namespace you want. Sometimes it's important to take control of building a dependency graph. For example, when there are multiple implementations of the same contract. In this case, tags will help:
interface IDependency { } class AbcDependency: IDependency { } class XyzDependency: IDependency { } class Dependency: IDependency { } interface IService { IDependency Dependency1 { get; } IDependency Dependency2 { get; } } class Service: IService { public Service( [Tag("Abc")] IDependency dependency1, [Tag("Xyz")] IDependency dependency2) { Dependency1 = dependency1; Dependency2 = dependency2; } public IDependency Dependency1 { get; } public IDependency Dependency2 { get; } } DI.Setup("Composition") .Bind<IDependency>("Abc").To<AbcDependency>() .Bind<IDependency>("Xyz").To<XyzDependency>() .Bind<IService>().To<Service>().Root<IService>("Root");See also DependencyAttribute.
See also OrdinalAttribute.
See also TypeAttribute.
Constructor TagAttribute(System.Object)
Creates an attribute instance.
- parameter tag - The injection tag. See also Tags(System.Object[]) .
TT
Represents the generic type arguments marker for a reference type.
DI.Setup("Composition") .Bind<IDependency<TT>>().To<Dependency<TT>>();TT1
Represents the generic type arguments marker for a reference type.
DI.Setup("Composition") .Bind<IDependency<TT1>>().To<Dependency<TT1>>();TT2
Represents the generic type arguments marker for a reference type.
DI.Setup("Composition") .Bind<IDependency<TT2>>().To<Dependency<TT2>>();TT3
Represents the generic type arguments marker for a reference type.
DI.Setup("Composition") .Bind<IDependency<TT3>>().To<Dependency<TT3>>();TT4
Represents the generic type arguments marker for a reference type.
DI.Setup("Composition") .Bind<IDependency<TT4>>().To<Dependency<TT4>>();TTCollection`1
Represents the generic type arguments marker for ICollection`1.
DI.Setup("Composition") .Bind<IDependency<TTCollection<TT>>>().To<Dependency<TTCollection<TT>>>();TTCollection1`1
Represents the generic type arguments marker for ICollection`1.
DI.Setup("Composition") .Bind<IDependency<TTCollection1<TT>>>().To<Dependency<TTCollection1<TT>>>();TTCollection2`1
Represents the generic type arguments marker for ICollection`1.
DI.Setup("Composition") .Bind<IDependency<TTCollection2<TT>>>().To<Dependency<TTCollection2<TT>>>();TTCollection3`1
Represents the generic type arguments marker for ICollection`1.
DI.Setup("Composition") .Bind<IDependency<TTCollection3<TT>>>().To<Dependency<TTCollection3<TT>>>();TTCollection4`1
Represents the generic type arguments marker for ICollection`1.
DI.Setup("Composition") .Bind<IDependency<TTCollection4<TT>>>().To<Dependency<TTCollection4<TT>>>();TTComparable
Represents the generic type arguments marker for IComparable.
DI.Setup("Composition") .Bind<IDependency<TTComparable>>().To<Dependency<TTComparable>>();TTComparable`1
Represents the generic type arguments marker for IComparable`1.
DI.Setup("Composition") .Bind<IDependency<TTComparable<TT>>>().To<Dependency<TTComparable<TT>>>();TTComparable1
Represents the generic type arguments marker for IComparable.
DI.Setup("Composition") .Bind<IDependency<TTComparable1>>().To<Dependency<TTComparable1>>();TTComparable1`1
Represents the generic type arguments marker for IComparable`1.
DI.Setup("Composition") .Bind<IDependency<TTComparable1<TT>>>().To<Dependency<TTComparable1<TT>>>();TTComparable2
Represents the generic type arguments marker for IComparable.
DI.Setup("Composition") .Bind<IDependency<TTComparable2>>().To<Dependency<TTComparable2>>();TTComparable2`1
Represents the generic type arguments marker for IComparable`1.
DI.Setup("Composition") .Bind<IDependency<TTComparable2<TT>>>().To<Dependency<TTComparable2<TT>>>();TTComparable3
Represents the generic type arguments marker for IComparable.
DI.Setup("Composition") .Bind<IDependency<TTComparable3>>().To<Dependency<TTComparable3>>();TTComparable3`1
Represents the generic type arguments marker for IComparable`1.
DI.Setup("Composition") .Bind<IDependency<TTComparable3<TT>>>().To<Dependency<TTComparable3<TT>>>();TTComparable4
Represents the generic type arguments marker for IComparable.
DI.Setup("Composition") .Bind<IDependency<TTComparable4>>().To<Dependency<TTComparable4>>();TTComparable4`1
Represents the generic type arguments marker for IComparable`1.
DI.Setup("Composition") .Bind<IDependency<TTComparable4<TT>>>().To<Dependency<TTComparable4<TT>>>();TTComparer`1
Represents the generic type arguments marker for IComparer`1.
DI.Setup("Composition") .Bind<IDependency<TTComparer<TT>>>().To<Dependency<TTComparer<TT>>>();TTComparer1`1
Represents the generic type arguments marker for IComparer`1.
DI.Setup("Composition") .Bind<IDependency<TTComparer1<TT>>>().To<Dependency<TTComparer1<TT>>>();TTComparer2`1
Represents the generic type arguments marker for IComparer`1.
DI.Setup("Composition") .Bind<IDependency<TTComparer2<TT>>>().To<Dependency<TTComparer2<TT>>>();TTComparer3`1
Represents the generic type arguments marker for IComparer`1.
DI.Setup("Composition") .Bind<IDependency<TTComparer3<TT>>>().To<Dependency<TTComparer3<TT>>>();TTComparer4`1
Represents the generic type arguments marker for IComparer`1.
DI.Setup("Composition") .Bind<IDependency<TTComparer4<TT>>>().To<Dependency<TTComparer4<TT>>>();TTDisposable
Represents the generic type arguments marker for IDisposable.
DI.Setup("Composition") .Bind<IDependency<TTDisposable>>().To<Dependency<TTDisposable>>();TTDisposable1
Represents the generic type arguments marker for IDisposable.
DI.Setup("Composition") .Bind<IDependency<TTDisposable1>>().To<Dependency<TTDisposable1>>();TTDisposable2
Represents the generic type arguments marker for IDisposable.
DI.Setup("Composition") .Bind<IDependency<TTDisposable2>>().To<Dependency<TTDisposable2>>();TTDisposable3
Represents the generic type arguments marker for IDisposable.
DI.Setup("Composition") .Bind<IDependency<TTDisposable3>>().To<Dependency<TTDisposable3>>();TTDisposable4
Represents the generic type arguments marker for IDisposable.
DI.Setup("Composition") .Bind<IDependency<TTDisposable4>>().To<Dependency<TTDisposable4>>();TTE
Represents the generic type arguments marker for a enum type.
DI.Setup("Composition") .Bind<IDependency<TTE>>().To<Dependency<TTE>>();TTE1
Represents the generic type arguments marker for a enum type.
DI.Setup("Composition") .Bind<IDependency<TTE1>>().To<Dependency<TTE1>>();TTE2
Represents the generic type arguments marker for a enum type.
DI.Setup("Composition") .Bind<IDependency<TTE2>>().To<Dependency<TTE2>>();TTE3
Represents the generic type arguments marker for a enum type.
DI.Setup("Composition") .Bind<IDependency<TTE3>>().To<Dependency<TTE3>>();TTE4
Represents the generic type arguments marker for a enum type.
DI.Setup("Composition") .Bind<IDependency<TTE4>>().To<Dependency<TTE4>>();TTEnumerable`1
Represents the generic type arguments marker for IEnumerable`1.
DI.Setup("Composition") .Bind<IDependency<TTEnumerable<TT>>>().To<Dependency<TTEnumerable<TT>>>();TTEnumerable1`1
Represents the generic type arguments marker for IEnumerable`1.
DI.Setup("Composition") .Bind<IDependency<TTEnumerable1<TT>>>().To<Dependency<TTEnumerable1<TT>>>();TTEnumerable2`1
Represents the generic type arguments marker for IEnumerable`1.
DI.Setup("Composition") .Bind<IDependency<TTEnumerable2<TT>>>().To<Dependency<TTEnumerable2<TT>>>();TTEnumerable3`1
Represents the generic type arguments marker for IEnumerable`1.
DI.Setup("Composition") .Bind<IDependency<TTEnumerable3<TT>>>().To<Dependency<TTEnumerable3<TT>>>();TTEnumerable4`1
Represents the generic type arguments marker for IEnumerable`1.
DI.Setup("Composition") .Bind<IDependency<TTEnumerable4<TT>>>().To<Dependency<TTEnumerable4<TT>>>();TTEnumerator`1
Represents the generic type arguments marker for IEnumerator`1.
DI.Setup("Composition") .Bind<IDependency<TTEnumerator<TT>>>().To<Dependency<TTEnumerator<TT>>>();TTEnumerator1`1
Represents the generic type arguments marker for IEnumerator`1.
DI.Setup("Composition") .Bind<IDependency<TTEnumerator1<TT>>>().To<Dependency<TTEnumerator1<TT>>>();TTEnumerator2`1
Represents the generic type arguments marker for IEnumerator`1.
DI.Setup("Composition") .Bind<IDependency<TTEnumerator2<TT>>>().To<Dependency<TTEnumerator2<TT>>>();TTEnumerator3`1
Represents the generic type arguments marker for IEnumerator`1.
DI.Setup("Composition") .Bind<IDependency<TTEnumerator3<TT>>>().To<Dependency<TTEnumerator3<TT>>>();TTEnumerator4`1
Represents the generic type arguments marker for IEnumerator`1.
DI.Setup("Composition") .Bind<IDependency<TTEnumerator4<TT>>>().To<Dependency<TTEnumerator4<TT>>>();TTEqualityComparer`1
Represents the generic type arguments marker for IEqualityComparer`1.
DI.Setup("Composition") .Bind<IDependency<TTEqualityComparer<TT>>>().To<Dependency<TTEqualityComparer<TT>>>();TTEqualityComparer1`1
Represents the generic type arguments marker for IEqualityComparer`1.
DI.Setup("Composition") .Bind<IDependency<TTEqualityComparer1<TT>>>().To<Dependency<TTEqualityComparer1<TT>>>();TTEqualityComparer2`1
Represents the generic type arguments marker for IEqualityComparer`1.
DI.Setup("Composition") .Bind<IDependency<TTEqualityComparer2<TT>>>().To<Dependency<TTEqualityComparer2<TT>>>();TTEqualityComparer3`1
Represents the generic type arguments marker for IEqualityComparer`1.
DI.Setup("Composition") .Bind<IDependency<TTEqualityComparer3<TT>>>().To<Dependency<TTEqualityComparer3<TT>>>();TTEqualityComparer4`1
Represents the generic type arguments marker for IEqualityComparer`1.
DI.Setup("Composition") .Bind<IDependency<TTEqualityComparer4<TT>>>().To<Dependency<TTEqualityComparer4<TT>>>();TTEquatable`1
Represents the generic type arguments marker for IEquatable`1.
DI.Setup("Composition") .Bind<IDependency<TTEquatable<TT>>>().To<Dependency<TTEquatable<TT>>>();TTEquatable1`1
Represents the generic type arguments marker for IEquatable`1.
DI.Setup("Composition") .Bind<IDependency<TTEquatable1<TT>>>().To<Dependency<TTEquatable1<TT>>>();TTEquatable2`1
Represents the generic type arguments marker for IEquatable`1.
DI.Setup("Composition") .Bind<IDependency<TTEquatable2<TT>>>().To<Dependency<TTEquatable2<TT>>>();TTEquatable3`1
Represents the generic type arguments marker for IEquatable`1.
DI.Setup("Composition") .Bind<IDependency<TTEquatable3<TT>>>().To<Dependency<TTEquatable3<TT>>>();TTEquatable4`1
Represents the generic type arguments marker for IEquatable`1.
DI.Setup("Composition") .Bind<IDependency<TTEquatable4<TT>>>().To<Dependency<TTEquatable4<TT>>>();TTList`1
Represents the generic type arguments marker for IList`1.
DI.Setup("Composition") .Bind<IDependency<TTList<TT>>>().To<Dependency<TTList<TT>>>();TTList1`1
Represents the generic type arguments marker for IList`1.
DI.Setup("Composition") .Bind<IDependency<TTList1<TT>>>().To<Dependency<TTList1<TT>>>();TTList2`1
Represents the generic type arguments marker for IList`1.
DI.Setup("Composition") .Bind<IDependency<TTList2<TT>>>().To<Dependency<TTList2<TT>>>();TTList3`1
Represents the generic type arguments marker for IList`1.
DI.Setup("Composition") .Bind<IDependency<TTList3<TT>>>().To<Dependency<TTList3<TT>>>();TTList4`1
Represents the generic type arguments marker for IList`1.
DI.Setup("Composition") .Bind<IDependency<TTList4<TT>>>().To<Dependency<TTList4<TT>>>();TTObservable`1
Represents the generic type arguments marker for IObservable`1.
DI.Setup("Composition") .Bind<IDependency<TTObservable<TT>>>().To<Dependency<TTObservable<TT>>>();TTObservable1`1
Represents the generic type arguments marker for IObservable`1.
DI.Setup("Composition") .Bind<IDependency<TTObservable1<TT>>>().To<Dependency<TTObservable1<TT>>>();TTObservable2`1
Represents the generic type arguments marker for IObservable`1.
DI.Setup("Composition") .Bind<IDependency<TTObservable2<TT>>>().To<Dependency<TTObservable2<TT>>>();TTObservable3`1
Represents the generic type arguments marker for IObservable`1.
DI.Setup("Composition") .Bind<IDependency<TTObservable3<TT>>>().To<Dependency<TTObservable3<TT>>>();TTObservable4`1
Represents the generic type arguments marker for IObservable`1.
DI.Setup("Composition") .Bind<IDependency<TTObservable4<TT>>>().To<Dependency<TTObservable4<TT>>>();TTObserver`1
Represents the generic type arguments marker for IObserver`1.
DI.Setup("Composition") .Bind<IDependency<TTObserver<TT>>>().To<Dependency<TTObserver<TT>>>();TTObserver1`1
Represents the generic type arguments marker for IObserver`1.
DI.Setup("Composition") .Bind<IDependency<TTObserver1<TT>>>().To<Dependency<TTObserver1<TT>>>();TTObserver2`1
Represents the generic type arguments marker for IObserver`1.
DI.Setup("Composition") .Bind<IDependency<TTObserver2<TT>>>().To<Dependency<TTObserver2<TT>>>();TTObserver3`1
Represents the generic type arguments marker for IObserver`1.
DI.Setup("Composition") .Bind<IDependency<TTObserver3<TT>>>().To<Dependency<TTObserver3<TT>>>();TTObserver4`1
Represents the generic type arguments marker for IObserver`1.
DI.Setup("Composition") .Bind<IDependency<TTObserver4<TT>>>().To<Dependency<TTObserver4<TT>>>();TTReadOnlyCollection`1
Represents the generic type arguments marker for IReadOnlyCollection`1.
TTReadOnlyCollection1`1
Represents the generic type arguments marker for IReadOnlyCollection`1.
TTReadOnlyCollection2`1
Represents the generic type arguments marker for IReadOnlyCollection`1.
TTReadOnlyCollection3`1
Represents the generic type arguments marker for IReadOnlyCollection`1.
TTReadOnlyCollection4`1
Represents the generic type arguments marker for IReadOnlyCollection`1.
TTReadOnlyList`1
Represents the generic type arguments marker for IReadOnlyList`1.
TTReadOnlyList1`1
Represents the generic type arguments marker for IReadOnlyList`1.
TTReadOnlyList2`1
Represents the generic type arguments marker for IReadOnlyList`1.
TTReadOnlyList3`1
Represents the generic type arguments marker for IReadOnlyList`1.
TTReadOnlyList4`1
Represents the generic type arguments marker for IReadOnlyList`1.
TTS
Represents the generic type arguments marker for a value type.
DI.Setup("Composition") .Bind<IDependency<TTS>>().To<Dependency<TTS>>();TTS1
Represents the generic type arguments marker for a value type.
DI.Setup("Composition") .Bind<IDependency<TTS1>>().To<Dependency<TTS1>>();TTS2
Represents the generic type arguments marker for a value type.
DI.Setup("Composition") .Bind<IDependency<TTS2>>().To<Dependency<TTS2>>();TTS3
Represents the generic type arguments marker for a value type.
DI.Setup("Composition") .Bind<IDependency<TTS3>>().To<Dependency<TTS3>>();TTS4
Represents the generic type arguments marker for a value type.
DI.Setup("Composition") .Bind<IDependency<TTS4>>().To<Dependency<TTS4>>();TTSet`1
Represents the generic type arguments marker for ISet`1.
DI.Setup("Composition") .Bind<IDependency<TTSet<TT>>>().To<Dependency<TTSet<TT>>>();TTSet1`1
Represents the generic type arguments marker for ISet`1.
DI.Setup("Composition") .Bind<IDependency<TTSet1<TT>>>().To<Dependency<TTSet1<TT>>>();TTSet2`1
Represents the generic type arguments marker for ISet`1.
DI.Setup("Composition") .Bind<IDependency<TTSet2<TT>>>().To<Dependency<TTSet2<TT>>>();TTSet3`1
Represents the generic type arguments marker for ISet`1.
DI.Setup("Composition") .Bind<IDependency<TTSet3<TT>>>().To<Dependency<TTSet3<TT>>>();TTSet4`1
Represents the generic type arguments marker for ISet`1.
DI.Setup("Composition") .Bind<IDependency<TTSet4<TT>>>().To<Dependency<TTSet4<TT>>>();TypeAttribute
The injection type can be defined manually using the
Type
attribute. This attribute explicitly overrides an injected type, otherwise it would be determined automatically based on the type of the constructor/method, property, or field parameter. This attribute is part of the API, but you can use your own attribute at any time, and this allows you to define them in the assembly and namespace you want.interface IDependency { } class AbcDependency: IDependency { } class XyzDependency: IDependency { } interface IService { IDependency Dependency1 { get; } IDependency Dependency2 { get; } } class Service: IService { public Service( [Type(typeof(AbcDependency))] IDependency dependency1, [Type(typeof(XyzDependency))] IDependency dependency2) { Dependency1 = dependency1; Dependency2 = dependency2; } public IDependency Dependency1 { get; } public IDependency Dependency2 { get; } } DI.Setup("Composition") .Bind<IService>().To<Service>().Root<IService>("Root");See also DependencyAttribute.
See also TagAttribute.
See also OrdinalAttribute.
Constructor TypeAttribute(System.Type)
Creates an attribute instance.
- parameter type - The injection type. See also Bind
1(System.Object[])_ and _Bind
1(System.Object[]).
- Auto-bindings
- Injections of abstractions
- Composition roots
- Resolve methods
- Simplified binding
- Factory
- Simplified factory
- Injection on demand
- Injections on demand with arguments
- Class arguments
- Root arguments
- Tags
- Smart tags
- Build up of an existing object
- Builder
- Builder with arguments
- Builders
- Builders with a name template
- Field injection
- Method injection
- Property injection
- Default values
- Required properties or fields
- Overrides
- Root binding
- Static root
- Async Root
- Consumer type
- Ref dependencies
- Roots
- Roots with filter
- Transient
- Singleton
- PerResolve
- PerBlock
- Scope
- Auto scoped
- Default lifetime
- Default lifetime for a type
- Default lifetime for a type and a tag
- Disposable singleton
- Async disposable singleton
- Async disposable scope
- Func
- Enumerable
- Enumerable generics
- Array
- Lazy
- Task
- ValueTask
- Manually started tasks
- Span and ReadOnlySpan
- Tuple
- Weak Reference
- Async Enumerable
- Service collection
- Func with arguments
- Func with tag
- Keyed service provider
- Service provider
- Service provider with scope
- Overriding the BCL binding
- Generics
- Generic composition roots
- Complex generics
- Generic composition roots with constraints
- Generic async composition roots with constraints
- Custom generic argument
- Build up of an existing generic object
- Generic root arguments
- Complex generic root arguments
- Generic builder
- Generic builders
- Generic roots
- Generic injections as required
- Generic injections as required with arguments
- Constructor ordinal attribute
- Dependency attribute
- Member ordinal attribute
- Tag attribute
- Type attribute
- Inject attribute
- Custom attributes
- Custom universal attribute
- Custom generic argument attribute
- Bind attribute
- Bind attribute with lifetime and tag
- Bind attribute for a generic type
- Resolve hint
- ThreadSafe hint
- OnDependencyInjection regular expression hint
- OnDependencyInjection wildcard hint
- OnCannotResolve regular expression hint
- OnCannotResolve wildcard hint
- OnNewInstance regular expression hint
- OnNewInstance wildcard hint
- ToString hint
- Check for a root
- Composition root kinds
- Factory with thread synchronization
- Root with name template
- Tag Any
- Tag Type
- Tag Unique
- Tag on injection site
- Tag on a constructor argument
- Tag on a member
- Tag on a method argument
- Tag on injection site with wildcards
- Dependent compositions
- Inheritance of compositions
- Accumulators
- Global compositions
- Partial class
- A few partial classes
- Thread-safe overrides
- Consumer types
- Tracking disposable instances per a composition root
- Tracking disposable instances in delegates
- Tracking disposable instances using pre-built classes
- Tracking disposable instances with different lifetimes
- Tracking async disposable instances per a composition root
- Tracking async disposable instances in delegates
- Exposed roots
- Exposed roots with tags
- Exposed roots via arg
- Exposed roots via root arg
- Exposed generic roots
- Exposed generic roots with args
- Console
- Unity
- UI
- Web
- Git repo with examples
Each generated class, hereafter called a composition, must be customized. Setup starts with a call to the Setup(string compositionTypeName)
method:
DI.Setup("Composition")
.Bind<IDependency>().To<Dependency>()
.Bind<IService>().To<Service>()
.Root<IService>("Root");
The following class will be generated
partial class Composition
{
// Default constructor
public Composition() { }
// Scope constructor
internal Composition(Composition parentScope) { }
// Composition root
public IService Root
{
get
{
return new Service(new Dependency());
}
}
public T Resolve<T>() { ... }
public T Resolve<T>(object? tag) { ... }
public object Resolve(Type type) { ... }
public object Resolve(Type type, object? tag) { ... }
}
The compositionTypeName parameter can be omitted
- if the setup is performed inside a partial class, then the composition will be created for this partial class
- for the case of a class with composition kind
CompositionKind.Global
, see this example
Setup arguments
The first parameter is used to specify the name of the composition class. All sets with the same name will be combined to create one composition class. Alternatively, this name may contain a namespace, e.g. a composition class is generated for Sample.Composition
:
namespace Sample
{
partial class Composition
{
...
}
}
The second optional parameter may have multiple values to determine the kind of composition.
This value is used by default. If this value is specified, a normal composition class will be created.
If you specify this value, the class will not be generated, but this setup can be used by others as a base setup. For example:
DI.Setup("BaseComposition", CompositionKind.Internal)
.Bind().To<Dependency>();
DI.Setup("Composition").DependsOn("BaseComposition")
.Bind().To<Service>();
If the CompositionKind.Public flag is set in the composition setup, it can also be the base for other compositions, as in the example above.
No composition class will be created when this value is specified, but this setup is the base setup for all setups in the current project, and DependsOn(...)
is not required.
Constructors
It's quite trivial, this constructor simply initializes the internal state.
It replaces the default constructor and is only created if at least one argument is specified. For example:
DI.Setup("Composition")
.Arg<string>("name")
.Arg<int>("id")
...
In this case, the constructor with arguments is as follows:
public Composition(string name, int id) { ... }
and there is no default constructor. It is important to remember that only those arguments that are used in the object graph will appear in the constructor. Arguments that are not involved cannot be defined, as they are omitted from the constructor parameters to save resources.
This constructor creates a composition instance for the new scope. This allows Lifetime.Scoped
to be applied. See this example for details.
Composition Roots
To create an object graph quickly and conveniently, a set of properties (or a methods) is formed. These properties/methods are here called roots of compositions. The type of a property/method is the type of the root object created by the composition. Accordingly, each invocation of a property/method leads to the creation of a composition with a root element of this type.
DI.Setup("Composition")
.Bind<IService>().To<Service>()
.Root<IService>("MyService");
var composition = new Composition();
var service = composition.MyService;
service = composition.Resolve<IService>();
service = composition.Resolve(typeof(IService));
In this case, the property for the IService type will be named MyService and will be available for direct use. The result of its use will be the creation of a composition of objects with the root of IService type:
public IService MyService
{
get
{
...
return new Service(...);
}
}
This is recommended way to create a composition root. A composition class can contain any number of roots.
In addition, the composition roots can be resolved using the Resolve()
methods:
service = composition.Resolve<IService>();
service = composition.Resolve(typeof(IService));
![TIP]
- There is no limit to the number of roots, but you should consider limiting the number of roots. Ideally, an application should have a single composition root
- The name of the composition root is arbitrarily chosen depending on its purpose, but should be restricted by the property naming conventions in C# since it is the same name as a property in the composition class
- It is recommended that composition roots be resolved using normal properties or methods instead of methods of type
Resolve()
.
If the root name is empty, an anonymous composition root with a random name is created:
private IService RootM07D16di_0001
{
get { ... }
}
These properties (or methods) have an arbitrary name and access modifier private
and cannot be used directly from the code. Do not attempt to use them, as their names are arbitrarily changed. Anonymous composition roots can be resolved by Resolve
methods:
DI.Setup("Composition")
.Bind<IService>().To<Service>()
.Root<IService>();
var composition = new Composition();
var service = composition.Resolve<IService>();
service = composition.Resolve(typeof(IService));
Methods "Resolve"
By default, a set of four Resolve methods is generated:
public T Resolve<T>() { ... }
public T Resolve<T>(object? tag) { ... }
public object Resolve(Type type) { ... }
public object Resolve(Type type, object? tag) { ... }
These methods can resolve both public and anonymous composition roots that do not depend on any arguments of the composition roots. They are useful when using the Service Locator approach, where the code resolves composition roots in place:
var composition = new Composition();
composition.Resolve<IService>();
This is a not recommended way to create composition roots because Resolve methods have a number of disadvantages:
- They provide access to an unlimited set of dependencies.
- Their use can potentially lead to runtime exceptions, for example, when the corresponding root has not been defined.
- Lead to performance degradation because they search for the root of a composition based on its type.
To control the generation of these methods, see the Resolve hint.
Provides a mechanism to release unmanaged resources. These methods are generated only if the composition contains at least one singleton/scoped instance that implements either the IDisposable and/or DisposeAsync interface. The Dispose()
or DisposeAsync()
method of the composition should be called to dispose of all created singleton/scoped objects:
using var composition = new Composition();
or
await using var composition = new Composition();
To dispose objects of other lifetimes please see this or this examples.
Setup hints
Hints are used to fine-tune code generation. Setup hints can be used as shown in the following example:
DI.Setup("Composition")
.Hint(Hint.Resolve, "Off")
.Hint(Hint.ThreadSafe, "Off")
.Hint(Hint.ToString, "On")
...
In addition, setup hints can be commented out before the Setup method as hint = value
. For example:
// Resolve = Off
// ThreadSafe = Off
DI.Setup("Composition")
...
Both approaches can be mixed:
// Resolve = Off
DI.Setup("Composition")
.Hint(Hint.ThreadSafe, "Off")
...
Hint | Values | C# version | Default |
---|---|---|---|
Resolve | On or Off | On | |
OnNewInstance | On or Off | 9.0 | Off |
OnNewInstancePartial | On or Off | On | |
OnNewInstanceImplementationTypeNameRegularExpression | Regular expression | .+ | |
OnNewInstanceImplementationTypeNameWildcard | Wildcard | * | |
OnNewInstanceTagRegularExpression | Regular expression | .+ | |
OnNewInstanceTagWildcard | Wildcard | * | |
OnNewInstanceLifetimeRegularExpression | Regular expression | .+ | |
OnNewInstanceLifetimeWildcard | Wildcard | * | |
OnDependencyInjection | On or Off | 9.0 | Off |
OnDependencyInjectionPartial | On or Off | On | |
OnDependencyInjectionImplementationTypeNameRegularExpression | Regular expression | .+ | |
OnDependencyInjectionImplementationTypeNameWildcard | Wildcard | * | |
OnDependencyInjectionContractTypeNameRegularExpression | Regular expression | .+ | |
OnDependencyInjectionContractTypeNameWildcard | Wildcard | * | |
OnDependencyInjectionTagRegularExpression | Regular expression | .+ | |
OnDependencyInjectionTagWildcard | Wildcard | * | |
OnDependencyInjectionLifetimeRegularExpression | Regular expression | .+ | |
OnDependencyInjectionLifetimeWildcard | Wildcard | * | |
OnCannotResolve | On or Off | 9.0 | Off |
OnCannotResolvePartial | On or Off | On | |
OnCannotResolveContractTypeNameRegularExpression | Regular expression | .+ | |
OnCannotResolveContractTypeNameWildcard | Wildcard | * | |
OnCannotResolveTagRegularExpression | Regular expression | .+ | |
OnCannotResolveTagWildcard | Wildcard | * | |
OnCannotResolveLifetimeRegularExpression | Regular expression | .+ | |
OnCannotResolveLifetimeWildcard | Wildcard | * | |
OnNewRoot | On or Off | Off | |
OnNewRootPartial | On or Off | On | |
ToString | On or Off | Off | |
ThreadSafe | On or Off | On | |
ResolveMethodModifiers | Method modifier | public | |
ResolveMethodName | Method name | Resolve | |
ResolveByTagMethodModifiers | Method modifier | public | |
ResolveByTagMethodName | Method name | Resolve | |
ObjectResolveMethodModifiers | Method modifier | public | |
ObjectResolveMethodName | Method name | Resolve | |
ObjectResolveByTagMethodModifiers | Method modifier | public | |
ObjectResolveByTagMethodName | Method name | Resolve | |
DisposeMethodModifiers | Method modifier | public | |
DisposeAsyncMethodModifiers | Method modifier | public | |
FormatCode | On or Off | Off | |
SeverityOfNotImplementedContract | Error or Warning or Info or Hidden | Error | |
Comments | On or Off | On | |
SkipDefaultConstructor | On or Off | Off | |
SkipDefaultConstructorImplementationTypeNameRegularExpression | Regular expression | .+ | |
SkipDefaultConstructorImplementationTypeNameWildcard | Wildcard | * | |
SkipDefaultConstructorLifetimeRegularExpression | Regular expression | .+ | |
SkipDefaultConstructorLifetimeWildcard | Wildcard | * | |
DisableAutoBinding | On or Off | Off | |
DisableAutoBindingImplementationTypeNameRegularExpression | Regular expression | .+ | |
DisableAutoBindingImplementationTypeNameWildcard | Wildcard | * | |
DisableAutoBindingLifetimeRegularExpression | Regular expression | .+ | |
DisableAutoBindingLifetimeWildcard | Wildcard | * |
The list of hints will be gradually expanded to meet the needs and desires for fine-tuning code generation. Please feel free to add your ideas.
Determines whether to generate Resolve methods. By default, a set of four Resolve methods are generated. Set this hint to Off to disable the generation of resolve methods. This will reduce the generation time of the class composition, and in this case no anonymous composition roots will be generated. The class composition will be smaller and will only have public roots. When the Resolve hint is disabled, only the public roots properties are available, so be sure to explicitly define them using the Root<T>(string name)
method with an explicit composition root name.
Determines whether to use the OnNewInstance partial method. By default, this partial method is not generated. This can be useful, for example, for logging purposes:
internal partial class Composition
{
partial void OnNewInstance<T>(ref T value, object? tag, object lifetime) =>
Console.WriteLine($"'{typeof(T)}'('{tag}') created.");
}
You can also replace the created instance with a T
type, where T
is the actual type of the created instance. To minimize performance loss when calling OnNewInstance, use the three hints below.
Determines whether to generate the OnNewInstance partial method. By default, this partial method is generated when the OnNewInstance hint is On
.
This is a regular expression for filtering by instance type name. This hint is useful when OnNewInstance is in On state and it is necessary to limit the set of types for which the OnNewInstance method will be called.
This is a Wildcard for filtering by instance type name. This hint is useful when OnNewInstance is in On state and it is necessary to limit the set of types for which the OnNewInstance method will be called.
This is a regular expression for filtering by tag. This hint is also useful when OnNewInstance is in On state and it is necessary to limit the set of tags for which the OnNewInstance method will be called.
This is a wildcard for filtering by tag. This hint is also useful when OnNewInstance is in On state and it is necessary to limit the set of tags for which the OnNewInstance method will be called.
This is a regular expression for filtering by lifetime. This hint is also useful when OnNewInstance is in On state and it is necessary to restrict the set of life times for which the OnNewInstance method will be called.
This is a wildcard for filtering by lifetime. This hint is also useful when OnNewInstance is in On state and it is necessary to restrict the set of life times for which the OnNewInstance method will be called.
Determines whether to use the OnDependencyInjection partial method when the OnDependencyInjection hint is On
to control dependency injection. By default it is On
.
// OnDependencyInjection = On
// OnDependencyInjectionPartial = Off
// OnDependencyInjectionContractTypeNameRegularExpression = ICalculator[\d]{1}
// OnDependencyInjectionTagRegularExpression = Abc
DI.Setup("Composition")
...
Determines whether to generate the OnDependencyInjection partial method to control dependency injection. By default, this partial method is not generated. It cannot have an empty body because of the return value. It must be overridden when it is generated. This may be useful, for example, for Interception Scenario.
// OnDependencyInjection = On
// OnDependencyInjectionContractTypeNameRegularExpression = ICalculator[\d]{1}
// OnDependencyInjectionTagRegularExpression = Abc
DI.Setup("Composition")
...
To minimize performance loss when calling OnDependencyInjection, use the three tips below.
This is a regular expression for filtering by instance type name. This hint is useful when OnDependencyInjection is in On state and it is necessary to restrict the set of types for which the OnDependencyInjection method will be called.
This is a wildcard for filtering by instance type name. This hint is useful when OnDependencyInjection is in On state and it is necessary to restrict the set of types for which the OnDependencyInjection method will be called.
This is a regular expression for filtering by the name of the resolving type. This hint is also useful when OnDependencyInjection is in On state and it is necessary to limit the set of permissive types for which the OnDependencyInjection method will be called.
This is a wildcard for filtering by the name of the resolving type. This hint is also useful when OnDependencyInjection is in On state and it is necessary to limit the set of permissive types for which the OnDependencyInjection method will be called.
This is a regular expression for filtering by tag. This hint is also useful when OnDependencyInjection is in the On state and you want to limit the set of tags for which the OnDependencyInjection method will be called.
This is a wildcard for filtering by tag. This hint is also useful when OnDependencyInjection is in the On state and you want to limit the set of tags for which the OnDependencyInjection method will be called.
This is a regular expression for filtering by lifetime. This hint is also useful when OnDependencyInjection is in On state and it is necessary to restrict the set of lifetime for which the OnDependencyInjection method will be called.
This is a wildcard for filtering by lifetime. This hint is also useful when OnDependencyInjection is in On state and it is necessary to restrict the set of lifetime for which the OnDependencyInjection method will be called.
Determines whether to use the OnCannotResolve<T>(...)
partial method to handle a scenario in which an instance cannot be resolved. By default, this partial method is not generated. Because of the return value, it cannot have an empty body and must be overridden at creation.
// OnCannotResolve = On
// OnCannotResolveContractTypeNameRegularExpression = string|DateTime
// OnDependencyInjectionTagRegularExpression = null
DI.Setup("Composition")
...
To avoid missing failed bindings by mistake, use the two relevant hints below.
Determines whether to generate the OnCannotResolve<T>(...)
partial method when the OnCannotResolve hint is On to handle a scenario in which an instance cannot be resolved. By default it is On
.
// OnCannotResolve = On
// OnCannotResolvePartial = Off
// OnCannotResolveContractTypeNameRegularExpression = string|DateTime
// OnDependencyInjectionTagRegularExpression = null
DI.Setup("Composition")
...
To avoid missing failed bindings by mistake, use the two relevant hints below.
Determines whether to use a static partial method OnNewRoot<TContract, T>(...)
to handle the new composition root registration event.
// OnNewRoot = On
DI.Setup("Composition")
...
Be careful, this hint disables checks for the ability to resolve dependencies!
Determines whether to generate a static partial method OnNewRoot<TContract, T>(...)
when the OnNewRoot hint is On
to handle the new composition root registration event.
// OnNewRootPartial = Off
DI.Setup("Composition")
...
This is a regular expression for filtering by the name of the resolving type. This hint is also useful when OnCannotResolve is in On state and it is necessary to limit the set of resolving types for which the OnCannotResolve method will be called.
This is a wildcard for filtering by the name of the resolving type. This hint is also useful when OnCannotResolve is in On state and it is necessary to limit the set of resolving types for which the OnCannotResolve method will be called.
This is a regular expression for filtering by tag. This hint is also useful when OnCannotResolve is in On state and it is necessary to limit the set of tags for which the OnCannotResolve method will be called.
This is a wildcard for filtering by tag. This hint is also useful when OnCannotResolve is in On state and it is necessary to limit the set of tags for which the OnCannotResolve method will be called.
This is a regular expression for filtering by lifetime. This hint is also useful when OnCannotResolve is in the On state and it is necessary to restrict the set of lives for which the OnCannotResolve method will be called.
This is a wildcard for filtering by lifetime. This hint is also useful when OnCannotResolve is in the On state and it is necessary to restrict the set of lives for which the OnCannotResolve method will be called.
Determines whether to generate the ToString() method. This method provides a class diagram in mermaid format. To see this diagram, just call the ToString method and copy the text to this site.
// ToString = On
DI.Setup("Composition")
.Bind<IService>().To<Service>()
.Root<IService>("MyService");
var composition = new Composition();
string classDiagram = composition.ToString();
This hint determines whether the composition of objects will be created in a thread-safe way. The default value of this hint is On. It is a good practice not to use threads when creating an object graph, in this case the hint can be disabled, which will result in a small performance gain. For example:
// ThreadSafe = Off
DI.Setup("Composition")
.Bind<IService>().To<Service>()
.Root<IService>("MyService");
Overrides the modifiers of the public T Resolve<T>()
method.
Overrides the method name for public T Resolve<T>()
.
Overrides the modifiers of the public T Resolve<T>(object? tag)
method.
Overrides the method name for public T Resolve<T>(object? tag)
.
Overrides the modifiers of the public object Resolve(Type type)
method.
Overrides the method name for public object Resolve(Type type)
.
Overrides the modifiers of the public object Resolve(Type type, object? tag)
method.
Overrides the method name for public object Resolve(Type type, object? tag)
.
Overrides the modifiers of the public void Dispose()
method.
Overrides the modifiers of the public ValueTask DisposeAsync()
method.
Specifies whether the generated code should be formatted. This option consumes a lot of CPU resources. This hint may be useful when studying the generated code or, for example, when making presentations.
Indicates the severity level of the situation when, in the binding, an implementation does not implement a contract. Possible values:
- "Error", it is default value.
- "Warning" - something suspicious but allowed.
- "Info" - information that does not indicate a problem.
- "Hidden" - what's not a problem.
Specifies whether the generated code should be commented.
// Represents the composition class
DI.Setup(nameof(Composition))
.Bind<IService>().To<Service>()
// Provides a composition root of my service
.Root<IService>("MyService");
Appropriate comments will be added to the generated Composition
class and the documentation for the class, depending on the IDE used, will look something like this:
Indicates whether System.Threading.Lock
should be used whenever possible instead of the classic approach of synchronizing object access using System.Threading.Monitor1.
On` by default.
DI.Setup(nameof(Composition))
.Hint(Hint.SystemThreadingLock, "Off")
.Bind().To<Service>()
.Root<Service>("MyService");
Then documentation for the composition root:
Code generation workflow
flowchart TD
start@{ shape: circle, label: "Start" }
setups[fa:fa-search DI setups analysis]
types["`fa:fa-search Types analysis
constructors/methods/properties/fields`"]
subgraph dep[Dependency graph]
option[fa:fa-search Selecting a next dependency set]
creating[fa:fa-cog Creating a dependency graph variant]
verification{fa:fa-check-circle Verification}
end
codeGeneration[fa:fa-code Code generation]
compilation[fa:fa-cog Compilation]
failed@{ shape: dbl-circ, label: "fa:fa-thumbs-down Compilation failed" }
success@{ shape: dbl-circ, label: "fa:fa-thumbs-up Success" }
start ==> setups
setups -.->|Has problems| failed
setups ==> types
types -.-> |Has problems| failed
types ==> option
option ==> creating
option -.-> |There are no other options| failed
creating ==> verification
verification -->|Has problems| option
verification ==>|Correct| codeGeneration
codeGeneration ==> compilation
compilation -.-> |Has problems| failed
compilation ==> success
Install the DI template Pure.DI.Templates
dotnet new install Pure.DI.Templates
Create a "Sample" console application from the template di
dotnet new di -o ./Sample
And run it
dotnet run --project Sample
For more information about the template, please see this page.
Version update
When updating the version, it is possible that the previous version of the code generator remains active and is used by compilation services. In this case, the old and new versions of the generator may conflict. For a project where the code generator is used, it is recommended to do the following:
- After updating the version, close the IDE if it is open
- Delete the obj and bin directories
- Execute the following commands one by one
dotnet build-server shutdown
dotnet restore
dotnet build
Disabling API generation
Pure.DI automatically generates its API. If an assembly already has the Pure.DI API, for example, from another assembly, it is sometimes necessary to disable its automatic generation to avoid ambiguity. To do this, you need to add a DefineConstants element to the project files of these modules. For example:
<PropertyGroup>
<DefineConstants>$(DefineConstants);PUREDI_API_SUPPRESSION</DefineConstants>
</PropertyGroup>
Display generated files
You can set project properties to save generated files and control their storage location. In the project file, add the <EmitCompilerGeneratedFiles>
element to the <PropertyGroup>
group and set its value to true
. Build the project again. The generated files are now created in the obj/Debug/netX.X/generated/Pure.DI/Pure.DI/Pure.DI.SourceGenerator directory. The path components correspond to the build configuration, the target framework, the source generator project name, and the full name of the generator type. You can choose a more convenient output folder by adding the <CompilerGeneratedFilesOutputPath>
element to the application project file. For example:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
<CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)Generated</CompilerGeneratedFilesOutputPath>
</PropertyGroup>
</Project>
Performance profiling
Please install the JetBrains.dotTrace.GlobalTools dotnet tool globally, for example:
dotnet tool install --global JetBrains.dotTrace.GlobalTools --version 2024.3.3
Or make sure it is installed. Add the following sections to the project:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<PureDIProfilePath>c:\profiling</PureDIProfilePath>
</PropertyGroup>
<ItemGroup>
<CompilerVisibleProperty Include="PureDIProfilePath" />
</ItemGroup>
</Project>
Replace the path like c:\profiling with the path where the profiling results will be saved.
Start the project build and wait until a file like c:\profiling\pure_di_????.dtt appears in the directory.
Examples of how to set up a composition
Articles
- RU New in Pure.DI by the end of 2024
- RU New in Pure.DI
- RU Pure.DI v2.1
- RU Pure.DI next step
- RU Pure.DI for .NET
RU DotNext video
Contextual AI needs to understand the situation itβs in. This means knowing details like API, usage scenarios, etc. This helps the AI give more relevant and personalized responses. So Markdown docs below can be useful if you or your team rely on an AI assistant to write code using Pure.DI:
AI Context file | Size | Tokens |
---|---|---|
AI_CONTEXT_SMALL.md | 28KB | 7K |
AI_CONTEXT_MEDIUM.md | 123KB | 31K |
AI_CONTEXT_LARGE.md | 410KB | 105K |
Thank you for your interest in contributing to the Pure.DI project! First of all, if you are going to make a big change or feature, please open a problem first. That way, we can coordinate and understand if the change you're going to work on fits with current priorities and if we can commit to reviewing and merging it within a reasonable timeframe. We don't want you to waste a lot of your valuable time on something that may not align with what we want for Pure.DI.
Contribution prerequisites: .NET SDK 9.0 or later is installed.
This repository contains the following directories and files:
π .github GitHub related files and main.yml for building using GitGub actions
π .logs temporary files for generating the README.md file
π .run configuration files for the Rider IDE
π benchmarks projects for performance measurement
π build application for building locally and using CI/CD
π docs resources for the README.md file
π readme sample scripts and examples of application implementations
π samples sample projects
π src source codes of the code generator and all libraries
|- π Pure.DI source code generator project
|- π Pure.DI.Abstractions abstraction library for Pure.DI
|- π Pure.DI.Core basic implementation of the source code generator
|- π Pure.DI.MS project for integration with Microsoft DI
|- π Pure.DI.Templates project templates for creating .NET projects using Pure.DI
|- π Directory.Build.props common MSBUILD properties for all source code generator projects
|- π Library.props common MSBUILD properties for library projects such as Pure.DI.Abstractions
π tests contains projects for testing
|- π Pure.DI.Example project for testing some integration scenarios
|- π Pure.DI.IntegrationTests integration tests
|- π Pure.DI.Tests unit tests for basic functionality
|- π Pure.DI.UsageTests usage tests, used for examples in README.md
|- π Directory.Build.props common MSBUILD properties for all test projects
π LICENSE license file
π build.cmd Windows script file to run one of the build steps, see description below
π build.sh Linux/Mac OS script file to run one of the build steps, see description below
π .space.kts build file using JetBrains space actions
π README.md this README.md file
π SECURITY.md policy file for handling security bugs and vulnerabilities
π Directory.Build.props basic MSBUILD properties for all projects
π Pure.DI.sln .NET solution file
The entire build logic is a regular console .NET application. You can use the build.cmd and build.sh files with the appropriate command in the parameters to perform all basic actions on the project, e.g:
Commands | Description |
---|---|
ai | Generate AI context |
bm, benchmarks | Run benchmarks |
c, check | Compatibility checks |
dp, deploy | Package deployment |
e, example | Create examples |
g, generator | Build and test the source code generator |
i, install | Install templates |
l, libs | Build and test libraries |
p, pack | Create NuGet packages |
perf, performance | Performance tests |
pb, publish | Publish the balazor web sssembly example |
r, readme | Generate README.md |
t, template | Create and deploy templates |
te, testexamples | Test examples |
u, upgrade | Upgrading the internal version of DI to the latest public version |
For example, to build and test the source code generator:
./build.sh generator
or to run benchmarks:
./build.cmd benchmarks
If you are using the Rider IDE, it already has a set of configurations to run these commands. This project uses C# interactive build automation system for .NET. This tool helps to make .NET builds more efficient.
Tests | Examples | Performance |
---|---|---|
Thanks!
Array
Method | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Gen1 | Allocated | Alloc Ratio |
---|---|---|---|---|---|---|---|---|---|
'Pure.DI composition root' | 198.9 ns | 4.01 ns | 7.44 ns | 0.97 | 0.05 | 0.0365 | - | 632 B | 1.00 |
'Hand Coded' | 205.2 ns | 4.15 ns | 7.80 ns | 1.00 | 0.05 | 0.0365 | - | 632 B | 1.00 |
'Pure.DI Resolve(Type)' | 213.2 ns | 4.22 ns | 6.70 ns | 1.04 | 0.05 | 0.0365 | - | 632 B | 1.00 |
'Pure.DI Resolve<T>()' | 218.9 ns | 4.33 ns | 6.07 ns | 1.07 | 0.05 | 0.0365 | - | 632 B | 1.00 |
LightInject | 222.2 ns | 4.42 ns | 4.14 ns | 1.08 | 0.05 | 0.0365 | - | 632 B | 1.00 |
DryIoc | 226.1 ns | 4.54 ns | 5.90 ns | 1.10 | 0.05 | 0.0365 | - | 632 B | 1.00 |
Unity | 8,851.1 ns | 89.93 ns | 75.10 ns | 43.20 | 1.68 | 0.8392 | - | 14520 B | 22.97 |
Autofac | 37,847.0 ns | 3,830.79 ns | 11,235.04 ns | 184.72 | 55.05 | 1.6785 | 0.0610 | 28976 B | 45.85 |
Enum
Method | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Gen1 | Allocated | Alloc Ratio |
---|---|---|---|---|---|---|---|---|---|
'Pure.DI Resolve<T>()' | 153.2 ns | 3.09 ns | 4.23 ns | 0.97 | 0.04 | 0.0198 | - | 344 B | 1.00 |
'Pure.DI Resolve(Type)' | 155.5 ns | 3.16 ns | 3.51 ns | 0.98 | 0.03 | 0.0198 | - | 344 B | 1.00 |
'Pure.DI composition root' | 157.2 ns | 3.03 ns | 4.45 ns | 0.99 | 0.04 | 0.0198 | - | 344 B | 1.00 |
'Hand Coded' | 158.2 ns | 3.15 ns | 4.21 ns | 1.00 | 0.04 | 0.0198 | - | 344 B | 1.00 |
'Microsoft DI' | 207.5 ns | 4.19 ns | 3.92 ns | 1.31 | 0.04 | 0.0272 | - | 472 B | 1.37 |
LightInject | 322.5 ns | 6.48 ns | 10.27 ns | 2.04 | 0.08 | 0.0496 | - | 856 B | 2.49 |
DryIoc | 328.0 ns | 6.51 ns | 10.51 ns | 2.07 | 0.09 | 0.0496 | - | 856 B | 2.49 |
Unity | 7,302.2 ns | 140.67 ns | 172.76 ns | 46.20 | 1.62 | 0.7935 | - | 13752 B | 39.98 |
Autofac | 26,766.0 ns | 239.86 ns | 200.30 ns | 169.34 | 4.65 | 1.6785 | 0.0610 | 29104 B | 84.60 |
Func
Method | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Allocated | Alloc Ratio |
---|---|---|---|---|---|---|---|---|
'Pure.DI composition root' | 10.88 ns | 0.095 ns | 0.084 ns | 0.94 | 0.01 | 0.0014 | 24 B | 1.00 |
'Hand Coded' | 11.54 ns | 0.166 ns | 0.155 ns | 1.00 | 0.02 | 0.0014 | 24 B | 1.00 |
'Pure.DI Resolve<T>()' | 14.76 ns | 0.104 ns | 0.098 ns | 1.28 | 0.02 | 0.0014 | 24 B | 1.00 |
'Pure.DI Resolve(Type)' | 15.49 ns | 0.109 ns | 0.097 ns | 1.34 | 0.02 | 0.0014 | 24 B | 1.00 |
DryIoc | 67.73 ns | 1.351 ns | 1.387 ns | 5.87 | 0.14 | 0.0069 | 120 B | 5.00 |
LightInject | 326.89 ns | 5.239 ns | 4.644 ns | 28.33 | 0.54 | 0.0291 | 504 B | 21.00 |
Unity | 3,686.49 ns | 20.737 ns | 18.383 ns | 319.54 | 4.45 | 0.1450 | 2552 B | 106.33 |
Autofac | 10,830.28 ns | 128.605 ns | 114.005 ns | 938.74 | 15.55 | 0.8087 | 14008 B | 583.67 |
Singleton
Method | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Gen1 | Allocated | Alloc Ratio |
---|---|---|---|---|---|---|---|---|---|
'Hand Coded' | 10.47 ns | 0.133 ns | 0.124 ns | 1.00 | 0.02 | 0.0014 | - | 24 B | 1.00 |
'Pure.DI composition root' | 11.12 ns | 0.304 ns | 0.338 ns | 1.06 | 0.03 | 0.0014 | - | 24 B | 1.00 |
'Pure.DI Resolve<T>()' | 13.07 ns | 0.345 ns | 0.369 ns | 1.25 | 0.04 | 0.0014 | - | 24 B | 1.00 |
'Pure.DI Resolve(Type)' | 13.46 ns | 0.297 ns | 0.278 ns | 1.29 | 0.03 | 0.0014 | - | 24 B | 1.00 |
DryIoc | 27.57 ns | 0.152 ns | 0.127 ns | 2.63 | 0.03 | 0.0014 | - | 24 B | 1.00 |
'Simple Injector' | 38.33 ns | 0.151 ns | 0.126 ns | 3.66 | 0.04 | 0.0014 | - | 24 B | 1.00 |
'Microsoft DI' | 39.94 ns | 0.301 ns | 0.267 ns | 3.82 | 0.05 | 0.0014 | - | 24 B | 1.00 |
LightInject | 887.91 ns | 3.402 ns | 3.016 ns | 84.84 | 1.01 | 0.0010 | - | 24 B | 1.00 |
Unity | 5,962.55 ns | 28.551 ns | 25.310 ns | 569.74 | 6.95 | 0.1831 | - | 3184 B | 132.67 |
Autofac | 19,999.91 ns | 158.901 ns | 140.862 ns | 1,911.07 | 25.52 | 1.3733 | 0.0305 | 24208 B | 1,008.67 |
'Castle Windsor' | 30,901.04 ns | 108.855 ns | 90.899 ns | 2,952.71 | 34.95 | 1.3428 | - | 23912 B | 996.33 |
Ninject | 117,479.34 ns | 2,330.050 ns | 2,589.845 ns | 11,225.60 | 273.58 | 4.1504 | 1.0986 | 73176 B | 3,049.00 |
Transient
Method | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Gen1 | Allocated | Alloc Ratio |
---|---|---|---|---|---|---|---|---|---|
'Pure.DI composition root' | 10.32 ns | 0.115 ns | 0.108 ns | 0.94 | 0.01 | 0.0014 | - | 24 B | 1.00 |
'Hand Coded' | 10.97 ns | 0.127 ns | 0.119 ns | 1.00 | 0.01 | 0.0014 | - | 24 B | 1.00 |
'Pure.DI Resolve<T>()' | 13.00 ns | 0.098 ns | 0.091 ns | 1.18 | 0.01 | 0.0014 | - | 24 B | 1.00 |
'Pure.DI Resolve(Type)' | 14.57 ns | 0.178 ns | 0.167 ns | 1.33 | 0.02 | 0.0014 | - | 24 B | 1.00 |
LightInject | 20.18 ns | 0.154 ns | 0.137 ns | 1.84 | 0.02 | 0.0014 | - | 24 B | 1.00 |
'Microsoft DI' | 26.82 ns | 0.098 ns | 0.082 ns | 2.44 | 0.03 | 0.0014 | - | 24 B | 1.00 |
DryIoc | 26.87 ns | 0.141 ns | 0.118 ns | 2.45 | 0.03 | 0.0014 | - | 24 B | 1.00 |
'Simple Injector' | 37.33 ns | 0.213 ns | 0.178 ns | 3.40 | 0.04 | 0.0014 | - | 24 B | 1.00 |
Unity | 9,258.36 ns | 37.403 ns | 33.157 ns | 843.68 | 9.30 | 0.2899 | - | 5176 B | 215.67 |
Autofac | 29,574.31 ns | 259.556 ns | 230.089 ns | 2,694.99 | 34.73 | 1.9226 | 0.0916 | 33224 B | 1,384.33 |
'Castle Windsor' | 58,089.75 ns | 113.928 ns | 95.135 ns | 5,293.50 | 56.04 | 3.1128 | - | 54360 B | 2,265.00 |
Ninject | 266,156.53 ns | 5,315.749 ns | 7,451.939 ns | 24,253.83 | 713.79 | 7.3242 | 1.9531 | 128736 B | 5,364.00 |
Benchmarks environment
BenchmarkDotNet v0.15.0, Linux Ubuntu 22.04.5 LTS (Jammy Jellyfish) (container)
Intel Xeon Platinum 8175M CPU 2.50GHz, 1 CPU, 2 logical cores and 1 physical core
.NET SDK 9.0.102
[Host] : .NET 9.0.1 (9.0.124.61010), X64 RyuJIT AVX-512F+CD+BW+DQ+VL
DefaultJob : .NET 9.0.1 (9.0.124.61010), X64 RyuJIT AVX-512F+CD+BW+DQ+VL