You can use the Transient<>(), Singleton<>(), PerResolve<>(), etc. methods. In this case binding will be performed for the implementation type itself, and if the implementation is not an abstract type or structure, for all abstract but NOT special types that are directly implemented.
This keeps lifetime configuration concise while preserving explicit lifetime semantics.
using System.Collections;
using Pure.DI;
// Specifies to create a partial class "Composition"
DI.Setup(nameof(Composition))
// The equivalent of the following:
// .Bind<IOrderRepository, IOrderNotification, OrderManager>()
// .As(Lifetime.PerBlock)
// .To<OrderManager>()
.PerBlock<OrderManager>()
// The equivalent of the following:
// .Bind<IShop, Shop>()
// .As(Lifetime.Transient)
// .To<Shop>()
// .Bind<IOrderNameFormatter, OrderNameFormatter>()
// .As(Lifetime.Transient)
// .To<OrderNameFormatter>()
.Transient<Shop, OrderNameFormatter>()
// Specifies to create a property "MyShop"
.Root<IShop>("MyShop");
var composition = new Composition();
var shop = composition.MyShop;
interface IManager;
class ManagerBase : IManager;
interface IOrderRepository;
interface IOrderNotification;
class OrderManager(IOrderNameFormatter orderNameFormatter) :
ManagerBase,
IOrderRepository,
IOrderNotification,
IDisposable,
IEnumerable<string>
{
public void Dispose() {}
public IEnumerator<string> GetEnumerator() =>
new List<string>
{
orderNameFormatter.Format(1),
orderNameFormatter.Format(2)
}.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
interface IOrderNameFormatter
{
string Format(int orderId);
}
class OrderNameFormatter : IOrderNameFormatter
{
public string Format(int orderId) => $"Order #{orderId}";
}
interface IShop;
class Shop(
OrderManager manager,
IOrderRepository repository,
IOrderNotification notification)
: IShop;Running this code sample locally
- Make sure you have the .NET SDK 10.0 or later installed
dotnet --list-sdk- Create a net10.0 (or later) console application
dotnet new console -n Sample- Add a reference to the NuGet package
dotnet add package Pure.DI- Copy the example code into the Program.cs file
You are ready to run the example 🚀
dotnet runThese methods perform the binding with appropriate lifetime:
- with the implementation type itself
- and if it is NOT an abstract type or structure
- with all abstract types that it directly implements
- exceptions are special types
Special types will not be added to bindings:
System.ObjectSystem.EnumSystem.MulticastDelegateSystem.DelegateSystem.Collections.IEnumerableSystem.Collections.Generic.IEnumerable<T>System.Collections.Generic.IList<T>System.Collections.Generic.ICollection<T>System.Collections.IEnumeratorSystem.Collections.Generic.IEnumerator<T>System.Collections.Generic.IReadOnlyList<T>System.Collections.Generic.IReadOnlyCollection<T>System.IDisposableSystem.IAsyncResultSystem.AsyncCallback
If you want to add your own special type, use the SpecialType<T>() call.
For class OrderManager, the PerBlock<OrderManager>() binding will be equivalent to the Bind<IOrderRepository, IOrderNotification, OrderManager>().As(Lifetime.PerBlock).To<OrderManager>() binding. The types IDisposable, IEnumerable<string> did not get into the binding because they are special from the list above. ManagerBase did not get into the binding because it is not abstract. IManager is not included because it is not implemented directly by class OrderManager.
| yes | OrderManager |
implementation type itself |
| yes | IOrderRepository |
directly implements |
| yes | IOrderNotification |
directly implements |
| no | IDisposable |
special type |
| no | IEnumerable<string> |
special type |
| no | ManagerBase |
non-abstract |
| no | IManager |
is not directly implemented by class OrderManager |
| Limitations: lifetime-specific shortcuts still rely on inferred contracts, so review inferred bindings carefully. | ||
| Common pitfalls: |
- Applying singleton shortcuts to stateful services without thread-safety guarantees.
- Assuming shortcut APIs bypass special-type exclusion rules. See also: Transient, Simplified binding.
The following partial class will be generated:
partial class Composition
{
public IShop MyShop
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
var perBlockOrderManager348 = new OrderManager(new OrderNameFormatter());
return new Shop(perBlockOrderManager348, perBlockOrderManager348, perBlockOrderManager348);
}
}
}Class diagram:
---
config:
maxTextSize: 2147483647
maxEdges: 2147483647
class:
hideEmptyMembersBox: true
---
classDiagram
OrderManager --|> IOrderRepository
OrderManager --|> IOrderNotification
OrderManager --|> IEnumerableᐸStringᐳ
Shop --|> IShop
OrderNameFormatter --|> IOrderNameFormatter
Composition ..> Shop : IShop MyShop
OrderManager *-- OrderNameFormatter : IOrderNameFormatter
Shop o-- "PerBlock" OrderManager : OrderManager
Shop o-- "PerBlock" OrderManager : IOrderRepository
Shop o-- "PerBlock" OrderManager : IOrderNotification
namespace Pure.DI.UsageTests.Basics.SimplifiedLifetimeBindingScenario {
class Composition {
<<partial>>
+IShop MyShop
}
class IOrderNameFormatter {
<<interface>>
}
class IOrderNotification {
<<interface>>
}
class IOrderRepository {
<<interface>>
}
class IShop {
<<interface>>
}
class OrderManager {
<<class>>
+OrderManager(IOrderNameFormatter orderNameFormatter)
}
class OrderNameFormatter {
<<class>>
+OrderNameFormatter()
}
class Shop {
<<class>>
+Shop(OrderManager manager, IOrderRepository repository, IOrderNotification notification)
}
}
namespace System.Collections.Generic {
class IEnumerableᐸStringᐳ {
<<interface>>
}
}