Skip to content

Latest commit

 

History

History
195 lines (164 loc) · 5.7 KB

File metadata and controls

195 lines (164 loc) · 5.7 KB

Simplified binding

You can call Bind() without type parameters to infer contracts from the implementation type. This reduces boilerplate while preserving compile-time graph validation.

using System.Collections;
using Pure.DI;

// Specifies to create a partial class "Composition"
DI.Setup(nameof(Composition))
    // 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.
    // Equivalent to:
    // .Bind<IOrderRepository, IOrderNotification, OrderManager>()
    //   .As(Lifetime.PerBlock)
    //   .To<OrderManager>()
    .Bind().As(Lifetime.PerBlock).To<OrderManager>()
    .Bind().To<Shop>()

    // 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 :
    ManagerBase,
    IOrderRepository,
    IOrderNotification,
    IDisposable,
    IEnumerable<string>
{
    public void Dispose() {}

    public IEnumerator<string> GetEnumerator() =>
        new List<string> { "Order #1", "Order #2" }.GetEnumerator();

    IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}

interface IShop;

class Shop(
    OrderManager manager,
    IOrderRepository repository,
    IOrderNotification notification)
    : IShop;
Running this code sample locally
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 run

In practice, most abstraction types can be inferred. The parameterless Bind() binds:

  • the implementation type itself
  • and, if it is NOT abstract,
    • all abstract types it directly implements
    • except special types

Special types will not be added to bindings:

  • System.Object
  • System.Enum
  • System.MulticastDelegate
  • System.Delegate
  • System.Collections.IEnumerable
  • System.Collections.Generic.IEnumerable<T>
  • System.Collections.Generic.IList<T>
  • System.Collections.Generic.ICollection<T>
  • System.Collections.IEnumerator
  • System.Collections.Generic.IEnumerator<T>
  • System.Collections.Generic.IReadOnlyList<T>
  • System.Collections.Generic.IReadOnlyCollection<T>
  • System.IDisposable
  • System.IAsyncResult
  • System.AsyncCallback

If you want to add your own special type, use the SpecialType<T>() call.

For class OrderManager, Bind().To<OrderManager>() is equivalent to Bind<IOrderRepository, IOrderNotification, OrderManager>().To<OrderManager>(). The types IDisposable and IEnumerable<string> are excluded because they are special. ManagerBase is excluded because it is not abstract. IManager is excluded because it is not implemented directly by OrderManager.

OrderManager implementation type itself
IOrderRepository directly implements
IOrderNotification directly implements
IDisposable special type
IEnumerable<string> special type
ManagerBase non-abstract
IManager is not directly implemented by class OrderManager
Limitations: inferred bindings include only directly implemented abstractions and exclude special types.
Common pitfalls:

The following partial class will be generated:

partial class Composition
{
  public IShop MyShop
  {
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    get
    {
      var perBlockOrderManager342 = new OrderManager();
      return new Shop(perBlockOrderManager342, perBlockOrderManager342, perBlockOrderManager342);
    }
  }
}

Class diagram:

---
 config:
  maxTextSize: 2147483647
  maxEdges: 2147483647
  class:
   hideEmptyMembersBox: true
---
classDiagram
	OrderManager --|> IOrderRepository
	OrderManager --|> IOrderNotification
	OrderManager --|> IEnumerableᐸStringᐳ
	Shop --|> IShop
	Composition ..> Shop : IShop MyShop
	Shop o-- "PerBlock" OrderManager : OrderManager
	Shop o-- "PerBlock" OrderManager : IOrderRepository
	Shop o-- "PerBlock" OrderManager : IOrderNotification
	namespace Pure.DI.UsageTests.Basics.SimplifiedBindingScenario {
		class Composition {
		<<partial>>
		+IShop MyShop
		}
		class IOrderNotification {
			<<interface>>
		}
		class IOrderRepository {
			<<interface>>
		}
		class IShop {
			<<interface>>
		}
		class OrderManager {
				<<class>>
			+OrderManager()
		}
		class Shop {
				<<class>>
			+Shop(OrderManager manager, IOrderRepository repository, IOrderNotification notification)
		}
	}
	namespace System.Collections.Generic {
		class IEnumerableᐸStringᐳ {
			<<interface>>
		}
	}
Loading