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 Lock _lock = new Lock();
private Random? _random;
public Program Root
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
var stateFunc = new Func<State>(() => {
if (_random is null)
using (_lock.EnterScope())
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 object Resolve(Type type) { ... }
}
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.
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
A universal DI attribute that allows to specify the tag and ordinal of an injection.
parameter tag - The injection tag. See also Tags(System.Object[]) .
parameter ordinal - The injection ordinal.
See also OrdinalAttribute.
See also TagAttribute.
Constructor DependencyAttribute(System.Object,System.Int32)
Creates an attribute instance.
parameter tag - The injection tag. See also Tags(System.Object[]) .
parameter ordinal - The injection ordinal.
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
Hints for the code generator and can be used to fine tune code generation.
// 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
On
orOff
. Determines whether to generateResolve
methods.On
by default.// 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 OnNewInstance
On
orOff
. Determines whether to use partialOnNewInstance
method.Off
by default.// 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>();See also Hint(Pure.DI.Hint,System.String).
Field OnNewInstancePartial
On
orOff
. Determines whether to generate partialOnNewInstance
method when the OnNewInstance hint isOn
.On
by default.// 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>();See also Hint(Pure.DI.Hint,System.String).
Field OnNewInstanceImplementationTypeNameRegularExpression
The regular expression to filter OnNewInstance by the instance type name. ".+" by 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>();See also Hint(Pure.DI.Hint,System.String).
Field OnNewInstanceImplementationTypeNameWildcard
The wildcard to filter OnNewInstance by the instance type name. "*" by 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(Hint.OnNewInstanceImplementationTypeNameWildcard, "*Dependency") .Bind<IDependency>().To<Dependency>();See also Hint(Pure.DI.Hint,System.String).
Field OnNewInstanceTagRegularExpression
The regular expression to filter OnNewInstance by the tag. ".+" by 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>();See also Hint(Pure.DI.Hint,System.String).
Field OnNewInstanceTagWildcard
The wildcard to filter OnNewInstance by the tag. "*" by 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>();See also Hint(Pure.DI.Hint,System.String).
Field OnNewInstanceLifetimeRegularExpression
The regular expression to filter OnNewInstance by the lifetime. ".+" by 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>();See also Hint(Pure.DI.Hint,System.String).
Field OnNewInstanceLifetimeWildcard
The wildcard to filter OnNewInstance by the lifetime. "*" by 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>();See also Hint(Pure.DI.Hint,System.String).
Field OnDependencyInjection
On
orOff
. Determines whether to use partialOnDependencyInjection
method to control of dependency injection.Off
by default.// 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>();See also Hint(Pure.DI.Hint,System.String).
Field OnDependencyInjectionPartial
On
orOff
. Determines whether to generate partialOnDependencyInjection
method when the OnDependencyInjection hint isOn
to control of dependency injection.On
by default.// 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>();See also Hint(Pure.DI.Hint,System.String).
Field OnDependencyInjectionImplementationTypeNameRegularExpression
The regular expression to filter OnDependencyInjection by the instance type name. ".+" by 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>();See also Hint(Pure.DI.Hint,System.String).
Field OnDependencyInjectionImplementationTypeNameWildcard
The wildcard to filter OnDependencyInjection by the instance type name. "*" by 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>();See also Hint(Pure.DI.Hint,System.String).
Field OnDependencyInjectionContractTypeNameRegularExpression
The regular expression to filter OnDependencyInjection by the resolving type name. ".+" by 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>();See also Hint(Pure.DI.Hint,System.String).
Field OnDependencyInjectionContractTypeNameWildcard
The wildcard to filter OnDependencyInjection by the resolving type name. "*" by 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.OnDependencyInjectionContractTypeName, "*IDependency") .Bind<IDependency>().To<Dependency>();See also Hint(Pure.DI.Hint,System.String).
Field OnDependencyInjectionTagRegularExpression
The regular expression to filter OnDependencyInjection by the tag. ".+" by 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>();See also Hint(Pure.DI.Hint,System.String).
Field OnDependencyInjectionTagWildcard
The wildcard to filter OnDependencyInjection by the tag. "*" by 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>();See also Hint(Pure.DI.Hint,System.String).
Field OnDependencyInjectionLifetimeRegularExpression
The regular expression to filter OnDependencyInjection by the lifetime. ".+" by 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>();See also Hint(Pure.DI.Hint,System.String).
Field OnDependencyInjectionLifetimeWildcard
The wildcard to filter OnDependencyInjection by the lifetime. ".+" by 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>();See also Hint(Pure.DI.Hint,System.String).
Field OnCannotResolve
On
orOff
. Determines whether to use a partialOnCannotResolve<T>(...)
method to handle a scenario in which the dependency cannot be resolved.Off
by default.// 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>();See also Hint(Pure.DI.Hint,System.String).
Field OnCannotResolvePartial
On
orOff
. Determines whether to generate a partialOnCannotResolve<T>(...)
method when theOnCannotResolve
hint isOn
to handle a scenario in which the dependency cannot be resolved.On
by default.// 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>();See also Hint(Pure.DI.Hint,System.String).
Field OnCannotResolveContractTypeNameRegularExpression
The regular expression to filter OnCannotResolve by the resolving type name. ".+" by 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>();See also Hint(Pure.DI.Hint,System.String).
Field OnCannotResolveContractTypeNameWildcard
The wildcard to filter OnCannotResolve by the resolving type name. "*" by 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>();See also Hint(Pure.DI.Hint,System.String).
Field OnCannotResolveTagRegularExpression
The regular expression to filter OnCannotResolve by the tag. ".+" by 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>();See also Hint(Pure.DI.Hint,System.String).
Field OnCannotResolveTagWildcard
The wildcard to filter OnCannotResolve by the tag. "*" by 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>();See also Hint(Pure.DI.Hint,System.String).
Field OnCannotResolveLifetimeRegularExpression
The regular expression to filter OnCannotResolve by the lifetime. ".+" by 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>();See also Hint(Pure.DI.Hint,System.String).
Field OnCannotResolveLifetimeWildcard
The wildcard to filter OnCannotResolve by the lifetime. "*" by 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>();See also Hint(Pure.DI.Hint,System.String).
Field OnNewRoot
On
orOff
. Determines whether to use a static partialOnNewRoot<T>(...)
method to handle the new composition root registration event.Off
by default.// 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>();See also Hint(Pure.DI.Hint,System.String).
Field OnNewRootPartial
On
orOff
. Determines whether to generate a static partialOnNewRoot<T>(...)
method when theOnNewRoot
hint isOn
to handle the new composition root registration event.On
by default.// 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>();See also Hint(Pure.DI.Hint,System.String).
Field ToString
On
orOff
. Determine if theToString()
method should be generated. This method provides a text-based class diagram in the format mermaid.Off
by default.// 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>();See also Hint(Pure.DI.Hint,System.String).
Field ThreadSafe
On
orOff
. This hint determines whether object composition will be created in a thread-safe manner.On
by default.// 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>();See also Hint(Pure.DI.Hint,System.String).
Field ResolveMethodModifiers
Overrides modifiers of the method
public T Resolve<T>()
. "public" by default.// 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>();See also Hint(Pure.DI.Hint,System.String).
Field ResolveMethodName
Overrides name of the method
public T Resolve<T>()
. "Resolve" by default.// 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>();See also Hint(Pure.DI.Hint,System.String).
Field ResolveByTagMethodModifiers
Overrides modifiers of the method
public T Resolve<T>(object? tag)
. "public" by default.// 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>();See also Hint(Pure.DI.Hint,System.String).
Field ResolveByTagMethodName
Overrides name of the method
public T Resolve<T>(object? tag)
. "Resolve" by default. 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>();See also Hint(Pure.DI.Hint,System.String).
Field ObjectResolveMethodModifiers
Overrides modifiers of the method
public object Resolve(Type type)
. "public" by default.// 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>();See also Hint(Pure.DI.Hint,System.String).
Field ObjectResolveMethodName
Overrides name of the method
public object Resolve(Type type)
. "Resolve" by default.// 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>();See also Hint(Pure.DI.Hint,System.String).
Field ObjectResolveByTagMethodModifiers
Overrides modifiers of the method
public object Resolve(Type type, object? tag)
. "public" by default.// 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>();See also Hint(Pure.DI.Hint,System.String).
Field ObjectResolveByTagMethodName
Overrides name of the method
public object Resolve(Type type, object? tag)
. "Resolve" by default.// 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>();See also Hint(Pure.DI.Hint,System.String).
Field DisposeMethodModifiers
Overrides modifiers of the method
public void Dispose()
. "public" by default.// 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>();See also Hint(Pure.DI.Hint,System.String).
Field DisposeAsyncMethodModifiers
Overrides modifiers of the method
public _ValueTask_ DisposeAsyncMethodModifiers()
. "public" by default.// 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>();See also Hint(Pure.DI.Hint,System.String).
Field FormatCode
On
orOff
. Specifies whether the generated code should be formatted. This option consumes a lot of CPU resources.Off
by default.// 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>();See also Hint(Pure.DI.Hint,System.String).
Field SeverityOfNotImplementedContract
Error
orWarning
orInfo
orHidden
. Indicates the severity level of the situation when, in the binding, an implementation does not implement a contract.Error
by default.// 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.SeverityOfNotImplementedContracts, "On") .Bind<IDependency>().To<Dependency>();See also Hint(Pure.DI.Hint,System.String).
Field Comments
On
orOff
. Specifies whether the generated code should be commented.On
by default.// 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>();See also Hint(Pure.DI.Hint,System.String).
Field SystemThreadingLock
On
orOff
. Indicates whether Lock should be used whenever possible instead of the classic approach of synchronizing object access using Monitor.On
by default.// SystemThreadingLock = Off DI.Setup("Composition") .Bind<IDependency>().To<Dependency>();or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition") .Hint(Hint.SystemThreadingLock, "Off") .Bind<IDependency>().To<Dependency>();See also Hint(Pure.DI.Hint,System.String).
IBinding
An API for a binding setup.
Method Bind(System.Object[])
Begins the binding definition for the implementation type itself, and if the implementation is not an abstract class or structure, for all abstract but NOT special types that are directly implemented. Special types include: 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 - The optional argument that specifies tags for a particular type of dependency binding.
returns Reference to the setup continuation chain.
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[])
Begins the definition of the binding.
DI.Setup("Composition") .Bind<IDependency>().To<Dependency>();The type of dependency to be bound. Common type markers such as TT, TTList`1 and others are also supported.
parameter tags - The optional argument that specifies tags for a particular type of dependency binding.
returns Reference to the setup continuation chain.
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[])
Begins binding definition for multiple dependencies. See Bind``1(System.Object[]) for examples. The type 1 of dependency to be bound.The type 2 of dependency to be bound.
parameter tags - The optional argument that specifies tags for a particular type of dependency binding.
returns Reference to the setup continuation chain.
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[])
Begins binding definition for multiple dependencies. See Bind``1(System.Object[]) for examples. The type 1 of dependency to be bound.The type 2 of dependency to be bound.The type 3 of dependency to be bound.
parameter tags - The optional argument that specifies tags for a particular type of dependency binding.
returns Reference to the setup continuation chain.
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[])
Begins binding definition for multiple dependencies. See Bind``1(System.Object[]) for examples. The type 1 of dependency to be bound.The type 2 of dependency to be bound.The type 3 of dependency to be bound.The type 3 of dependency to be bound.
parameter tags - The optional argument that specifies tags for a particular type of dependency binding.
returns Reference to the setup continuation chain.
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)
Determines the Lifetime of a binding.
DI.Setup("Composition") .Bind<IDependency>().As(Lifetime.Singleton).To<Dependency>();
parameter lifetime - The Lifetime of a binding
returns Reference to the setup continuation chain.
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[])
Defines the binding tags. 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>().Tags("Abc").To<AbcDependency>() .Bind<IDependency>().Tags("Xyz").To<XyzDependency>() .Bind<IService>().To<Service>().Root<IService>("Root");
parameter tags - The binding tags.
returns Reference to the setup continuation chain.
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
Completes the binding chain by specifying the implementation.
DI.Setup("Composition") .Bind<IDependency>().To<Dependency>();The implementation type. Also supports generic type markers such as TT, TTList`1, and others.
- returns Reference to the setup continuation chain.
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})
Completes the binding chain by specifying the implementation using a factory method. It allows you to manually create an instance, call the necessary methods, initialize properties, fields, etc.
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 - An expression for manually creating and initializing an instance. The implementation type.
- returns Reference to the setup continuation chain.
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).
Method To``1(System.String)
Completes the binding chain by specifying the implementation using a source code statement.
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 statement The implementation type.
- returns Reference to the setup continuation chain.
See also Bind``1(System.Object[]).
Method To``2(System.Func{``0,``1})
Completes the binding chain by specifying the implementation using a simplified factory method. It allows you to manually create an instance, call the necessary methods, initialize properties, fields, etc. Each parameter of this factory method represents a dependency injection. Starting with C# 10, you can also put the TagAttribute in front of the parameter to specify the tag of the injected dependency.
DI.Setup(nameof(Composition)) .Bind<IDependency>().To(( Dependency dependency) => { dependency.Initialize(); return dependency; });A variant using _TagAttribute_:
DI.Setup(nameof(Composition)) .Bind<IDependency>().To(( [Tag("some tag")] Dependency dependency) => { dependency.Initialize(); return dependency; });
- parameter factory - An expression for manually creating and initializing an instance. Type #1 of injected dependency.The implementation type.
- returns Reference to the setup continuation chain.
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})
Completes the binding chain by specifying the implementation using a simplified factory method. It allows you to manually create an instance, call the necessary methods, initialize properties, fields, etc. Each parameter of this factory method represents a dependency injection. Starting with C# 10, you can also put the TagAttribute in front of the parameter to specify the tag of the injected dependency.
DI.Setup(nameof(Composition)) .Bind<IDependency>().To(( Dependency dependency, DateTimeOffset time) => { dependency.Initialize(time); return dependency; });A 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 - An expression for manually creating and initializing an instance. Type #1 of injected dependency.Type #2 of injected dependency.The implementation type.
- returns Reference to the setup continuation chain.
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})
Completes the binding chain by specifying the implementation using a simplified factory method. It allows you to manually create an instance, call the necessary methods, initialize properties, fields, etc. Each parameter of this factory method represents a dependency injection. Starting with C# 10, you can also put the TagAttribute in front of the parameter to specify the tag of the injected dependency.
- parameter factory - An expression for manually creating and initializing an instance. Type #1 of injected dependency.Type #2 of injected dependency.Type #3 of injected dependency.The implementation type.
- returns Reference to the setup continuation chain.
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
An API for a Dependency Injection setup.
See also Setup(System.String,Pure.DI.CompositionKind).
Method Bind(System.Object[])
Begins the binding definition for the implementation type itself, and if the implementation is not an abstract class or structure, for all abstract but NOT special types that are directly implemented. Special types include: 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 - The optional argument that specifies tags for a particular type of dependency binding.
returns Reference to the setup continuation chain.
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[])
Begins the definition of the binding.
DI.Setup("Composition") .Bind<IService>().To<Service>();The type of dependency to be bound.
parameter tags - The optional argument that specifies tags for a particular type of dependency binding.
returns Reference to the setup continuation chain.
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[])
Begins binding definition for multiple dependencies. See Bind``1(System.Object[]) for examples. The type 1 of dependency to be bound.The type 2 of dependency to be bound.
parameter tags - The optional argument that specifies tags for a particular type of dependency binding.
returns Reference to the setup continuation chain.
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[])
Begins binding definition for multiple dependencies. See Bind``1(System.Object[]) for examples. The type 1 of dependency to be bound.The type 2 of dependency to be bound.The type 3 of dependency to be bound.
parameter tags - The optional argument that specifies tags for a particular type of dependency binding.
returns Reference to the setup continuation chain.
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[])
Begins binding definition for multiple dependencies. See Bind``1(System.Object[]) for examples. The type 1 of dependency to be bound.The type 2 of dependency to be bound.The type 3 of dependency to be bound.The type 4 of dependency to be bound.
parameter tags - The optional argument that specifies tags for a particular type of dependency binding.
returns Reference to the setup continuation chain.
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[])
Begins the definition of the binding with Root``1(System.String,System.Object,Pure.DI.RootKinds) applied.
DI.Setup("Composition") .RootBind<IService>();The type of dependency to be bound.
parameter name - Specifies the name of the root of the composition. If the value is empty, a private root will be created, which can be used when calling
Resolve
methods. The name supports templating: TemplateDescription{type}Will be replaced by the short name of the root type without its namespaces.{TYPE}Will be replaced with the full name of the root type.{tag}Will be replaced with the first tag name.parameter kind - The optional argument specifying the kind for the root of the composition.
parameter tags - The optional argument that specifies tags for a particular type of dependency binding. If is is not empty, the first tag is used for the root.
returns Reference to the setup continuation chain.
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[])
Indicates the use of some single or multiple setups as base setups by name.
DI.Setup("Composition") .DependsOn(nameof(CompositionBase));
parameter setupNames - A set of names for the basic setups on which this one depends.
returns Reference to the setup continuation chain.
See also Setup(System.String,Pure.DI.CompositionKind).
Method GenericTypeArgumentAttribute``1
Specifies a custom generic type argument attribute.
[AttributeUsage(AttributeTargets.Interface | AttributeTargets.Class | AttributeTargets.Struct)] class MyGenericTypeArgumentAttribute : Attribute; [MyGenericTypeArgument] interface TTMy; DI.Setup("Composition") .GenericTypeAttribute<MyGenericTypeArgumentAttribute>() .Bind<IDependency<TTMy>>().To<Dependency<TTMy>>();The attribute type.
- returns Reference to the setup continuation chain.
See also GenericTypeArgumentAttribute``1.
Method TypeAttribute``1(System.Int32)
Specifies a custom attribute that overrides the injection type.
DI.Setup("Composition") .TypeAttribute<MyTypeAttribute>();
- parameter typeArgumentPosition - The optional parameter that specifies the position of the type parameter in the attribute constructor. 0 by default. See predefined attribute TypeAttribute``1(System.Int32). The attribute type.
- returns Reference to the setup continuation chain.
See also TypeAttribute.
Method TagAttribute``1(System.Int32)
Specifies a tag attribute that overrides the injected tag.
DI.Setup("Composition") .TagAttribute<MyTagAttribute>();
- parameter tagArgumentPosition - The optional parameter that specifies the position of the tag parameter in the attribute constructor. 0 by default. See the predefined TagAttribute``1(System.Int32) attribute. The attribute type.
- returns Reference to the setup continuation chain.
See also TagAttribute.
Method OrdinalAttribute``1(System.Int32)
Specifies a custom attribute that overrides the injection ordinal.
DI.Setup("Composition") .OrdinalAttribute<MyOrdinalAttribute>();
- parameter ordinalArgumentPosition - The optional parameter that specifies the position of the ordinal parameter in the attribute constructor. 0 by default. See the predefined OrdinalAttribute``1(System.Int32) attribute. The attribute type.
- returns Reference to the setup continuation chain.
See also OrdinalAttribute.
Method DefaultLifetime(Pure.DI.Lifetime)
Overrides the default Lifetime for all bindings further down the chain. If not specified, the Transient lifetime is used.
DI.Setup("Composition") .DefaultLifetime(Lifetime.Singleton);
parameter lifetime - The default lifetime.
returns Reference to the setup continuation chain.
See also Lifetime.
See also As(Pure.DI.Lifetime).
Method DefaultLifetime``1(Pure.DI.Lifetime,System.Object[])
Overrides the default Lifetime for all bindings can be casted to type further down the chain.
DI.Setup("Composition") .DefaultLifetime<IMySingleton>(Lifetime.Singleton);DI.Setup("Composition") .DefaultLifetime<IMySingleton>(Lifetime.Singleton, "my tag");
parameter lifetime - The default lifetime.
parameter tags - The optional argument specifying the binding tags for which it will set the default lifetime. If not specified, the default lifetime will be set for any tags. The default lifetime will be applied to bindings if the implementation class can be cast to type .
returns Reference to the setup continuation chain.
See also Lifetime.
See also As(Pure.DI.Lifetime).
Method Arg``1(System.String,System.Object[])
Adds a partial class argument and replaces the default constructor by adding this argument as a parameter. It is only created if this argument is actually used.
DI.Setup("Composition") .Arg<int>("id");
parameter name - The argument name. The name supports templating: TemplateDescription{type}Will be replaced by the short name of the argument type without its namespaces.{TYPE}Will be replaced with the full name of the argument type.{tag}Will be replaced with the first tag name.
parameter tags - The optional argument that specifies the tags for the argument. The argument type.
returns Reference to the setup continuation chain.
See also RootArg``1(System.String,System.Object[]).
Method RootArg``1(System.String,System.Object[])
Adds a root argument to use as a root parameter.
DI.Setup("Composition") .RootArg<int>("id");
parameter name - The argument name. The name supports templating: TemplateDescription{type}Will be replaced by the short name of the argument type without its namespaces.{TYPE}Will be replaced with the full name of the argument type.{tag}Will be replaced with the first tag name.
parameter tags - The optional argument that specifies the tags for the argument. The argument type.
returns Reference to the setup continuation chain.
See also Arg``1(System.String,System.Object[]).
Method Root``1(System.String,System.Object,Pure.DI.RootKinds)
Specifying the root of the composition.
DI.Setup("Composition") .Root<Service>("MyService");DI.Setup("Composition") .Root<Service>("My{type}");
parameter name - Specifies the name of the root of the composition. If the value is empty, a private root will be created, which can be used when calling
Resolve
methods. The name supports templating: TemplateDescription{type}Will be replaced by the short name of the root type without its namespaces.{TYPE}Will be replaced with the full name of the root type.{tag}Will be replaced with the root tag name.parameter tag - The optional argument specifying the tag for the root of the composition.
parameter kind - The optional argument specifying the kind for the root of the composition. The composition root type.
returns Reference to the setup continuation chain.
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)
Specifies to define composition roots for all types inherited from !:T available at compile time at the point where the method is called.
DI.Setup("Composition") .Roots<IService>();DI.Setup("Composition") .Roots<IService>("Root{type}", filter: "*MyService");
parameter name - Specifies the name of the roots of the composition. If the value is empty, private roots will be created, which can be used when calling
Resolve
methods. The name supports templating: TemplateDescription{type}Will be replaced by the short name of the type without its namespaces.{TYPE}Will be replaced with the full name of the type.parameter kind - The optional argument specifying the kind for the root of the composition.
parameter filter - A wildcard to filter root types by their full name. The composition root base type.
returns Reference to the setup continuation chain.
See also Root``1(System.String,System.Object,Pure.DI.RootKinds).
Method Builder``1(System.String,Pure.DI.RootKinds)
Specifies the method of the composition builder. The first argument to the method will always be the instance to be built. The remaining arguments to this method will be listed in the order in which they are defined in the setup.Specifies to create a composition builder method. The first argument to the method will always be the instance to be built. The remaining arguments to this method will be listed in the order in which they are defined in the setup.
DI.Setup("Composition") .Builder<Service>("BuildUpMyService");
parameter name - Specifies the name of the builder. The default name is "BuildUp". The name supports templating: TemplateDescription{type}Will be replaced by the short name of the type without its namespaces.{TYPE}Will be replaced with the full name of the type.
parameter kind - The optional argument specifying the kind for the root of the composition. The composition root type.
returns Reference to the setup continuation chain.
See also Builders``1(System.String,Pure.DI.RootKinds,System.String).
Method Builders``1(System.String,Pure.DI.RootKinds,System.String)
Specifies to define builders for all types inherited from !:T available at compile time at the point where the method is called.
DI.Setup("Composition") .Builders<Service>();DI.Setup("Composition") .Builder<Service>("BuildUp");DI.Setup("Composition") .Builder<Service>("BuildUp{type}", filter: "*MyService");
parameter name - Specifies the name of the builders. The default name is "BuildUp". The name supports templating: TemplateDescription{type}Will be replaced by the short name of the type without its namespaces.{TYPE}Will be replaced with the full name of the type.
parameter kind - The optional argument specifying the kind for the root of the composition.
parameter filter - A wildcard to filter builder types by their full name. The composition root base type.
returns Reference to the setup continuation chain.
See also Builder``1(System.String,Pure.DI.RootKinds).
Method Hint(Pure.DI.Hint,System.String)
Defines a hint for fine-tuning code generation.
DI.Setup("Composition") .Hint(Resolve, "Off");
parameter hint - The hint type.
parameter value - The hint value.
returns Reference to the setup continuation chain.
See also Hint.
Method Accumulate``2(Pure.DI.Lifetime[])
Registers an accumulator for instances.
DI.Setup("Composition") .Accumulate<IDisposable, MyAccumulator>(Lifetime.Transient);
- parameter lifetimes - Lifetime of the instances to be accumulated. Instances with lifetime Singleton, Scoped, or PerResolve only accumulate in an accumulator that is NOT lazily created. The type of instance. All instances that can be cast to this type will be aacumulated.The type of accumulator. It must have a public constructor without parameters and a
Add
method with a single argument that allows you to add an instance of type .- returns Reference to the setup continuation chain.
See also Lifetime.
Method GenericTypeArgument``1
Specifies a custom generic type argument.
interface TTMy; DI.Setup("Composition") .GenericTypeArgument<TTMy>() .Bind<IDependency<TTMy>>().To<Dependency<TTMy>>();The generic type marker.
- returns Reference to the setup continuation chain.
See also GenericTypeArgumentAttribute``1.
IContext
Injection context. Cannot be used outside of the binding setup.
Property Tag
The tag that was used to inject the current object in the object graph. Cannot be used outside of 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 types of consumers for which the instance is created. Cannot be used outside of the binding setup. Guaranteed to contain at least one element.
See also To
1(System.Func{Pure.DI.IContext,
0}).Method Inject``1(``0@)
Injects an instance of type
T
. Cannot be used outside of 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 of 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 of 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}).IOwned
This abstraction allows a disposable object to be disposed of.
See also Owned.
See also Accumulate``2(Pure.DI.Lifetime[]).
Lifetime
Binding lifetimes.
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
Specifies to create a new dependency instance each time. This is the default value and can be omitted.
DI.Setup("Composition") .Bind<IDependency>().As(Lifetime.Transient).To<Dependency>();This is the default lifetime, it can be omitted, for example:
DI.Setup("Composition") .Bind<IDependency>().To<Dependency>();Field Singleton
Ensures that there will be a single instance of the dependency for each composition.
DI.Setup("Composition") .Bind<IDependency>().As(Lifetime.Singleton).To<Dependency>();Field PerResolve
Guarantees that there will be a single instance of the dependency for each root of the composition.
DI.Setup("Composition") .Bind<IDependency>().As(Lifetime.PerResolve).To<Dependency>();Field PerBlock
Does not guarantee that there will be a single instance of the dependency for each root of the composition, but is useful to reduce the number of instances of type.
DI.Setup("Composition") .Bind<IDependency>().As(Lifetime.PerBlock).To<Dependency>();Field Scoped
Ensures that there will be a single instance of the dependency for each scope.
DI.Setup("Composition") .Bind<IDependency>().As(Lifetime.Singleton).To<Dependency>();OrdinalAttribute
Represents an ordinal attribute. 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. 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)
Creates an attribute instance.
- parameter ordinal - The injection ordinal.
Owned
Performs accumulation and disposal of disposable objects.
See also IOwned.
See also Accumulate``2(Pure.DI.Lifetime[]).
Method Dispose
Owned`1
Contains a value and gives the ability to dispose of that value. Type of value owned. See also IOwned.
See also Owned.
See also Accumulate``2(Pure.DI.Lifetime[]).
Field Value
Own value.
Constructor Owned`1(`0,Pure.DI.IOwned)
Creates a new instance.
parameter value - Own value.
parameter owned - The abstraction allows a disposable object to be disposed of.
Method Dispose
RootKinds
Determines a kind of root of the composition.
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
Specifies to use the default composition root kind.
Field Public
Specifies to use a
public
access modifier for the root of the composition.Field Internal
Specifies to use a
internal
access modifier for the root of the composition.Field Private
Specifies to use a
private
access modifier for the root of the composition.Field Property
Specifies to create a composition root as a property.
Field Method
Specifies to create a composition root as a method.
Field Static
Specifies to create a static root of the composition.
Field Partial
Specifies to create a partial root of the composition.
Field Exposed
Specifies to create a exposed root of the composition.
See also BindAttribute.
Field Protected
Specifies to use a
protected
access modifier for the root of the composition.Tag
Represents well known tags.
See also Bind``1(System.Object[]).
See also Tags(System.Object[]).
Field Unique
Unique tag. Begins the definition of the binding.
DI.Setup("Composition") .Bind<IService>(Tag.Unique).To<Service1>() .Bind<IService>(Tag.Unique).To<Service1>() .Root<IEnumerable<IService>>("Root");Field Type
Tag of target implementation type.
DI.Setup("Composition") .Bind<IService>(Tag.Type).To<Service>() .Root<IService>("Root", typeof(Service));Method On(System.String[])
This tag allows you to determine which binding will be used for explicit injection for a particular injection site.
DI.Setup("Composition") .Bind(Tag.On("MyNamespace.Service.Service:dep")) .To<Dependency>() .Bind().To<Service>() .Root<IService>("Root");
- parameter injectionSites - Set of labels for inection each, must be specified in a special format: ..[:argument]. The argument is specified only for the constructor and methods. The wildcards '*' and '?' are supported. All names are case-sensitive. The global namespace prefix 'global::' must be omitted.
Method OnConstructorArg``1(System.String)
This tag allows you to determine which binding will be used for explicit injection for a particular constructor argument.
DI.Setup("Composition") .Bind(Tag.OnConstructorArg<Service>("dep")) .To<Dependency>() .Bind().To<Service>() .Root<IService>("Root");
- parameter argName - The name of the constructor argument.
Method OnMember``1(System.String)
This tag allows you to define which binding will be used for explicit injection for property or field of the type.
DI.Setup("Composition") .Bind(Tag.OnMember<Service>("DepProperty")) .To<Dependency>() .Bind().To<Service>() .Root<IService>("Root");
- parameter memberName - The name of the type member.
Method OnMethodArg``1(System.String,System.String)
This tag allows you to determine which binding will be used for explicit injection for a particular method argument.
DI.Setup("Composition") .Bind(Tag.OnMethodArg<Service>("DoSomething", "state")) .To<Dependency>() .Bind().To<Service>() .Root<IService>("Root");
parameter methodName - The name of the type method.
parameter argName - The name of the method argument.
Field UsingDeclarations
Atomically generated smart tag with value "UsingDeclarations". It's used for:
class _Generator__CompositionClassBuilder_ <-- _IBuilder`2_(UsingDeclarations) -- _UsingDeclarationsBuilder_ as _PerBlock_
Field GenericType
Atomically generated smart tag with value "GenericType". It's used for:
class _Generator__TypeResolver_ <-- _IIdGenerator_(GenericType) -- _IdGenerator_ as _PerResolve_
Field CompositionClass
Atomically generated smart tag with value "CompositionClass". It's used for:
class _Generator__CodeBuilder_ <-- _IBuilder`2_(CompositionClass) -- _CompositionClassBuilder_ as _PerBlock_
Field Injection
Atomically generated smart tag with value "Injection".
Field UniqueTag
Atomically generated smart tag with value "UniqueTag". It's used for:
class _Generator__ApiInvocationProcessor_ <-- (UniqueTag) -- _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.
TT1
Represents the generic type arguments marker for a reference type.
TT2
Represents the generic type arguments marker for a reference type.
TT3
Represents the generic type arguments marker for a reference type.
TT4
Represents the generic type arguments marker for a reference type.
TTCollection`1
Represents the generic type arguments marker for ICollection>T>.
TTCollection1`1
Represents the generic type arguments marker for ICollection>T>.
TTCollection2`1
Represents the generic type arguments marker for ICollection>T>.
TTCollection3`1
Represents the generic type arguments marker for ICollection>T>.
TTCollection4`1
Represents the generic type arguments marker for ICollection>T>.
TTComparable
Represents the generic type arguments marker for IComparable.
TTComparable`1
Represents the generic type arguments marker for IComparable>T>.
TTComparable1
Represents the generic type arguments marker for IComparable.
TTComparable1`1
Represents the generic type arguments marker for IComparable>T>.
TTComparable2
Represents the generic type arguments marker for IComparable.
TTComparable2`1
Represents the generic type arguments marker for IComparable>T>.
TTComparable3
Represents the generic type arguments marker for IComparable.
TTComparable3`1
Represents the generic type arguments marker for IComparable>T>.
TTComparable4
Represents the generic type arguments marker for IComparable.
TTComparable4`1
Represents the generic type arguments marker for IComparable>T>.
TTComparer`1
Represents the generic type arguments marker for IComparer>T>.
TTComparer1`1
Represents the generic type arguments marker for IComparer>T>.
TTComparer2`1
Represents the generic type arguments marker for IComparer>T>.
TTComparer3`1
Represents the generic type arguments marker for IComparer>T>.
TTComparer4`1
Represents the generic type arguments marker for IComparer>T>.
TTDictionary`2
Represents the generic type arguments marker for IDictionary>TKey, TValue>.
TTDictionary1`2
Represents the generic type arguments marker for IDictionary>TKey, TValue>.
TTDictionary2`2
Represents the generic type arguments marker for IDictionary>TKey, TValue>.
TTDictionary3`2
Represents the generic type arguments marker for IDictionary>TKey, TValue>.
TTDictionary4`2
Represents the generic type arguments marker for IDictionary>TKey, TValue>.
TTDisposable
Represents the generic type arguments marker for IDisposable.
TTDisposable1
Represents the generic type arguments marker for IDisposable.
TTDisposable2
Represents the generic type arguments marker for IDisposable.
TTDisposable3
Represents the generic type arguments marker for IDisposable.
TTDisposable4
Represents the generic type arguments marker for IDisposable.
TTE
Represents the generic type arguments marker for a enum type.
TTE1
Represents the generic type arguments marker for a enum type.
TTE2
Represents the generic type arguments marker for a enum type.
TTE3
Represents the generic type arguments marker for a enum type.
TTE4
Represents the generic type arguments marker for a enum type.
TTEnumerable`1
Represents the generic type arguments marker for IEnumerable>T>.
TTEnumerable1`1
Represents the generic type arguments marker for IEnumerable>T>.
TTEnumerable2`1
Represents the generic type arguments marker for IEnumerable>T>.
TTEnumerable3`1
Represents the generic type arguments marker for IEnumerable>T>.
TTEnumerable4`1
Represents the generic type arguments marker for IEnumerable>T>.
TTEnumerator`1
Represents the generic type arguments marker for IEnumerator>T>.
TTEnumerator1`1
Represents the generic type arguments marker for IEnumerator>T>.
TTEnumerator2`1
Represents the generic type arguments marker for IEnumerator>T>.
TTEnumerator3`1
Represents the generic type arguments marker for IEnumerator>T>.
TTEnumerator4`1
Represents the generic type arguments marker for IEnumerator>T>.
TTEqualityComparer`1
Represents the generic type arguments marker for IEqualityComparer>T>.
TTEqualityComparer1`1
Represents the generic type arguments marker for IEqualityComparer>T>.
TTEqualityComparer2`1
Represents the generic type arguments marker for IEqualityComparer>T>.
TTEqualityComparer3`1
Represents the generic type arguments marker for IEqualityComparer>T>.
TTEqualityComparer4`1
Represents the generic type arguments marker for IEqualityComparer>T>.
TTEquatable`1
Represents the generic type arguments marker for IEquatable>T>.
TTEquatable1`1
Represents the generic type arguments marker for IEquatable>T>.
TTEquatable2`1
Represents the generic type arguments marker for IEquatable>T>.
TTEquatable3`1
Represents the generic type arguments marker for IEquatable>T>.
TTEquatable4`1
Represents the generic type arguments marker for IEquatable>T>.
TTList`1
Represents the generic type arguments marker for IList>T>.
TTList1`1
Represents the generic type arguments marker for IList>T>.
TTList2`1
Represents the generic type arguments marker for IList>T>.
TTList3`1
Represents the generic type arguments marker for IList>T>.
TTList4`1
Represents the generic type arguments marker for IList>T>.
TTObservable`1
Represents the generic type arguments marker for IObservable>T>.
TTObservable1`1
Represents the generic type arguments marker for IObservable>T>.
TTObservable2`1
Represents the generic type arguments marker for IObservable>T>.
TTObservable3`1
Represents the generic type arguments marker for IObservable>T>.
TTObservable4`1
Represents the generic type arguments marker for IObservable>T>.
TTObserver`1
Represents the generic type arguments marker for IObserver>T>.
TTObserver1`1
Represents the generic type arguments marker for IObserver>T>.
TTObserver2`1
Represents the generic type arguments marker for IObserver>T>.
TTObserver3`1
Represents the generic type arguments marker for IObserver>T>.
TTObserver4`1
Represents the generic type arguments marker for IObserver>T>.
TTReadOnlyCollection`1
Represents the generic type arguments marker for IReadOnlyCollection>T>.
TTReadOnlyCollection1`1
Represents the generic type arguments marker for IReadOnlyCollection>T>.
TTReadOnlyCollection2`1
Represents the generic type arguments marker for IReadOnlyCollection>T>.
TTReadOnlyCollection3`1
Represents the generic type arguments marker for IReadOnlyCollection>T>.
TTReadOnlyCollection4`1
Represents the generic type arguments marker for IReadOnlyCollection>T>.
TTReadOnlyList`1
Represents the generic type arguments marker for IReadOnlyList>T>.
TTReadOnlyList1`1
Represents the generic type arguments marker for IReadOnlyList>T>.
TTReadOnlyList2`1
Represents the generic type arguments marker for IReadOnlyList>T>.
TTReadOnlyList3`1
Represents the generic type arguments marker for IReadOnlyList>T>.
TTReadOnlyList4`1
Represents the generic type arguments marker for IReadOnlyList>T>.
TTS
Represents the generic type arguments marker for a value type.
TTS1
Represents the generic type arguments marker for a value type.
TTS2
Represents the generic type arguments marker for a value type.
TTS3
Represents the generic type arguments marker for a value type.
TTS4
Represents the generic type arguments marker for a value type.
TTSet`1
Represents the generic type arguments marker for ISet>T>.
TTSet1`1
Represents the generic type arguments marker for ISet>T>.
TTSet2`1
Represents the generic type arguments marker for ISet>T>.
TTSet3`1
Represents the generic type arguments marker for ISet>T>.
TTSet4`1
Represents the generic type arguments marker for ISet>T>.
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
- 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
- Root binding
- Async Root
- Consumer types
- 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
- 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
- Root with mame template
- 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
- Accumulators
- Global compositions
- Partial class
- A few partial classes
- 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
- DI tracing via serilog
- 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");
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.
If the root name is empty, a private composition root with a random name is created:
private IService RootM07D16di_0001
{
get { ... }
}
This root is available in Resolve methods in the same way as public roots. For example:
DI.Setup("Composition")
.Bind<IService>().To<Service>()
.Root<IService>();
These properties 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. Private composition roots can be resolved by Resolve methods.
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 private 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")
...
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 private 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 | 25KB | 6K |
AI_CONTEXT_MEDIUM.md | 124KB | 31K |
AI_CONTEXT_LARGE.md | 369KB | 94K |
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, ai | Generate AI context |
bm, benchmarks, benchmarks | Run benchmarks |
c, check, check | Compatibility checks |
dp, deploy, deploy | Package deployment |
e, example, example | Create examples |
g, generator, generator | Build and test the source code generator |
i, install, install | Install templates |
l, libs, libs | Build and test libraries |
p, pack, pack | Create NuGet packages |
perf, performance, performance | Performance tests |
pb, publish, publish | Publish the balazor web sssembly example |
r, readme, readme | Generate README.md |
t, template, template | Create and deploy templates |
te, testexamples, testexamples | Test examples |
u, upgrade, 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 | Median | Ratio | RatioSD | Gen0 | Gen1 | Allocated | Alloc Ratio |
---|---|---|---|---|---|---|---|---|---|---|
'Pure.DI composition root' | 88.33 ns | 1.075 ns | 1.006 ns | 88.58 ns | 0.94 | 0.03 | 0.0377 | - | 632 B | 1.00 |
'Pure.DI Resolve<T>()' | 91.94 ns | 1.832 ns | 2.445 ns | 91.66 ns | 0.98 | 0.04 | 0.0377 | - | 632 B | 1.00 |
'Pure.DI Resolve(Type)' | 92.65 ns | 2.244 ns | 6.366 ns | 89.18 ns | 0.98 | 0.07 | 0.0377 | - | 632 B | 1.00 |
'Hand Coded' | 94.24 ns | 1.883 ns | 2.578 ns | 94.06 ns | 1.00 | 0.04 | 0.0377 | - | 632 B | 1.00 |
DryIoc | 99.10 ns | 0.999 ns | 0.834 ns | 98.91 ns | 1.05 | 0.03 | 0.0377 | - | 632 B | 1.00 |
LightInject | 103.24 ns | 2.119 ns | 4.183 ns | 102.65 ns | 1.10 | 0.05 | 0.0377 | - | 632 B | 1.00 |
Unity | 4,510.09 ns | 74.628 ns | 66.155 ns | 4,488.31 ns | 47.89 | 1.47 | 0.8621 | 0.0076 | 14520 B | 22.97 |
Autofac | 15,134.66 ns | 110.608 ns | 86.355 ns | 15,131.24 ns | 160.72 | 4.45 | 1.7090 | 0.0610 | 28976 B | 45.85 |
Enum
Method | Mean | Error | StdDev | Median | Ratio | RatioSD | Gen0 | Gen1 | Allocated | Alloc Ratio |
---|---|---|---|---|---|---|---|---|---|---|
'Pure.DI composition root' | 64.36 ns | 1.282 ns | 2.919 ns | 62.75 ns | 1.00 | 0.05 | 0.0205 | - | 344 B | 1.00 |
'Hand Coded' | 64.49 ns | 0.791 ns | 0.661 ns | 64.47 ns | 1.00 | 0.01 | 0.0205 | - | 344 B | 1.00 |
'Pure.DI Resolve<T>()' | 65.26 ns | 0.965 ns | 0.903 ns | 65.56 ns | 1.01 | 0.02 | 0.0205 | - | 344 B | 1.00 |
'Pure.DI Resolve(Type)' | 65.43 ns | 1.004 ns | 0.784 ns | 65.23 ns | 1.01 | 0.02 | 0.0205 | - | 344 B | 1.00 |
'Microsoft DI' | 93.40 ns | 1.322 ns | 1.172 ns | 92.96 ns | 1.45 | 0.02 | 0.0281 | - | 472 B | 1.37 |
LightInject | 147.58 ns | 1.650 ns | 1.544 ns | 147.96 ns | 2.29 | 0.03 | 0.0510 | - | 856 B | 2.49 |
DryIoc | 147.61 ns | 1.110 ns | 0.984 ns | 147.54 ns | 2.29 | 0.03 | 0.0510 | - | 856 B | 2.49 |
Unity | 3,736.48 ns | 73.272 ns | 68.539 ns | 3,739.88 ns | 57.94 | 1.18 | 0.8202 | 0.0076 | 13752 B | 39.98 |
Autofac | 15,610.79 ns | 288.580 ns | 595.967 ns | 15,436.50 ns | 242.08 | 9.47 | 1.7395 | 0.0610 | 29104 B | 84.60 |
Func
Method | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Gen1 | Allocated | Alloc Ratio |
---|---|---|---|---|---|---|---|---|---|
'Pure.DI composition root' | 4.382 ns | 0.0561 ns | 0.0525 ns | 0.84 | 0.01 | 0.0014 | - | 24 B | 1.00 |
'Hand Coded' | 5.193 ns | 0.0649 ns | 0.0542 ns | 1.00 | 0.01 | 0.0014 | - | 24 B | 1.00 |
'Pure.DI Resolve<T>()' | 5.914 ns | 0.0753 ns | 0.0667 ns | 1.14 | 0.02 | 0.0014 | - | 24 B | 1.00 |
'Pure.DI Resolve(Type)' | 6.375 ns | 0.0465 ns | 0.0388 ns | 1.23 | 0.01 | 0.0014 | - | 24 B | 1.00 |
DryIoc | 28.979 ns | 0.3875 ns | 0.3435 ns | 5.58 | 0.08 | 0.0072 | - | 120 B | 5.00 |
LightInject | 155.185 ns | 2.9628 ns | 2.7714 ns | 29.89 | 0.60 | 0.0300 | - | 504 B | 21.00 |
Unity | 1,760.400 ns | 12.4774 ns | 11.6714 ns | 339.03 | 3.99 | 0.1507 | - | 2552 B | 106.33 |
Autofac | 5,745.474 ns | 36.1642 ns | 30.1988 ns | 1,106.51 | 12.28 | 0.8316 | 0.0076 | 14008 B | 583.67 |
Singleton
Method | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Gen1 | Allocated | Alloc Ratio |
---|---|---|---|---|---|---|---|---|---|
'Hand Coded' | 3.016 ns | 0.0721 ns | 0.0602 ns | 1.00 | 0.03 | 0.0014 | - | 24 B | 1.00 |
'Pure.DI composition root' | 3.337 ns | 0.0778 ns | 0.0728 ns | 1.11 | 0.03 | 0.0014 | - | 24 B | 1.00 |
'Pure.DI Resolve<T>()' | 3.517 ns | 0.0602 ns | 0.0533 ns | 1.17 | 0.03 | 0.0014 | - | 24 B | 1.00 |
'Pure.DI Resolve(Type)' | 4.649 ns | 0.1417 ns | 0.3832 ns | 1.54 | 0.13 | 0.0014 | - | 24 B | 1.00 |
DryIoc | 11.388 ns | 0.0389 ns | 0.0304 ns | 3.78 | 0.07 | 0.0014 | - | 24 B | 1.00 |
'Simple Injector' | 16.630 ns | 0.0782 ns | 0.0693 ns | 5.52 | 0.11 | 0.0014 | - | 24 B | 1.00 |
'Microsoft DI' | 19.551 ns | 0.0684 ns | 0.0606 ns | 6.49 | 0.12 | 0.0014 | - | 24 B | 1.00 |
LightInject | 426.861 ns | 1.0945 ns | 0.9702 ns | 141.59 | 2.70 | 0.0014 | - | 24 B | 1.00 |
Unity | 2,645.530 ns | 47.7345 ns | 66.9171 ns | 877.51 | 27.40 | 0.1869 | - | 3184 B | 132.67 |
Autofac | 9,723.452 ns | 60.9124 ns | 53.9972 ns | 3,225.24 | 63.41 | 1.4343 | 0.0458 | 24208 B | 1,008.67 |
'Castle Windsor' | 16,991.331 ns | 93.5701 ns | 87.5255 ns | 5,635.97 | 110.23 | 1.4038 | - | 23912 B | 996.33 |
Ninject | 67,297.995 ns | 1,045.7465 ns | 927.0271 ns | 22,322.54 | 516.33 | 4.2725 | 1.0986 | 73176 B | 3,049.00 |
Transient
Method | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Gen1 | Allocated | Alloc Ratio |
---|---|---|---|---|---|---|---|---|---|
'Pure.DI composition root' | 3.491 ns | 0.1203 ns | 0.2764 ns | 0.97 | 0.09 | 0.0014 | - | 24 B | 1.00 |
'Hand Coded' | 3.619 ns | 0.1132 ns | 0.1952 ns | 1.00 | 0.07 | 0.0014 | - | 24 B | 1.00 |
'Pure.DI Resolve<T>()' | 4.417 ns | 0.1377 ns | 0.3429 ns | 1.22 | 0.11 | 0.0014 | - | 24 B | 1.00 |
'Pure.DI Resolve(Type)' | 4.649 ns | 0.1431 ns | 0.1338 ns | 1.29 | 0.08 | 0.0014 | - | 24 B | 1.00 |
LightInject | 7.043 ns | 0.0902 ns | 0.0754 ns | 1.95 | 0.10 | 0.0014 | - | 24 B | 1.00 |
'Microsoft DI' | 10.357 ns | 0.1357 ns | 0.1133 ns | 2.87 | 0.15 | 0.0014 | - | 24 B | 1.00 |
DryIoc | 10.673 ns | 0.1197 ns | 0.1119 ns | 2.96 | 0.16 | 0.0014 | - | 24 B | 1.00 |
'Simple Injector' | 14.594 ns | 0.1373 ns | 0.1217 ns | 4.04 | 0.21 | 0.0014 | - | 24 B | 1.00 |
Unity | 4,320.577 ns | 85.0619 ns | 175.6675 ns | 1,197.13 | 78.58 | 0.3052 | - | 5176 B | 215.67 |
Autofac | 12,616.111 ns | 227.4971 ns | 201.6703 ns | 3,495.62 | 189.02 | 1.9836 | 0.0916 | 33224 B | 1,384.33 |
'Castle Windsor' | 27,766.858 ns | 312.7020 ns | 277.2021 ns | 7,693.52 | 405.54 | 3.2349 | 0.0305 | 54360 B | 2,265.00 |
Ninject | 148,286.554 ns | 3,309.2559 ns | 9,600.7521 ns | 41,086.58 | 3,398.59 | 7.5684 | 1.4648 | 128736 B | 5,364.00 |
Benchmarks environment
BenchmarkDotNet v0.14.0, Windows 10 (10.0.19045.4894/22H2/2022Update)
AMD Ryzen 9 5900X, 1 CPU, 24 logical and 12 physical cores
.NET SDK 9.0.100
[Host] : .NET 9.0.0 (9.0.24.52809), X64 RyuJIT AVX2
DefaultJob : .NET 9.0.0 (9.0.24.52809), X64 RyuJIT AVX2