Skip to content

Latest commit

 

History

History
170 lines (141 loc) · 5.34 KB

simplified-binding.md

File metadata and controls

170 lines (141 loc) · 5.34 KB

Simplified binding

CSharp

You can use the Bind(...) method without type parameters. 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.

interface IDependencyBase;

class DependencyBase : IDependencyBase;

interface IDependency;

interface IOtherDependency;

class Dependency :
    DependencyBase,
    IDependency,
    IOtherDependency,
    IDisposable,
    IEnumerable<string>
{
    public void Dispose() { }

    public IEnumerator<string> GetEnumerator() =>
        new List<string> { "abc" }.GetEnumerator();

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

interface IService;

class Service(
    Dependency dependencyImpl,
    IDependency dependency,
    IOtherDependency otherDependency)
    : IService;

// 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.
    // So that's the equivalent of the following:
    // .Bind<IDependency, IOtherDependency, Dependency>()
    //  .As(Lifetime.PerBlock)
    //  .To<Dependency>()
    .Bind().As(Lifetime.PerBlock).To<Dependency>()
    .Bind().To<Service>()

    // Specifies to create a property "MyService"
    .Root<IService>("MyService");

var composition = new Composition();
var service = composition.MyService;

As practice has shown, in most cases it is possible to define abstraction types in bindings automatically. That's why we added API Bind() method without type parameters to define abstractions in bindings. It is the Bind() method that performs the binding:

  • 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.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.IIReadOnlyList<T>
  • System.Collections.Generic.IReadOnlyCollection<T>
  • System.IDisposable
  • System.IAsyncResult
  • System.AsyncCallback

For class Dependency, the Bind().To<Dependency>() binding will be equivalent to the Bind<IDependency, IOtherDependency, Dependency>().To<Dependency>() binding. The types IDisposable, IEnumerable<string> did not get into the binding because they are special from the list above. DependencyBase did not get into the binding because it is not abstract. IDependencyBase is not included because it is not implemented directly by class Dependency.

Dependency implementation type itself
IDependency directly implements
IOtherDependency directly implements
IDisposable special type
IEnumerable<string> special type
DependencyBase non-abstract
IDependencyBase is not directly implemented by class Dependency

The following partial class will be generated:

partial class Composition
{
  private readonly Composition _root;

  [OrdinalAttribute(20)]
  public Composition()
  {
    _root = this;
  }

  internal Composition(Composition parentScope)
  {
    _root = (parentScope ?? throw new ArgumentNullException(nameof(parentScope)))._root;
  }

  public IService MyService
  {
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    get
    {
      Dependency perBlockDependency1 = new Dependency();
      return new Service(perBlockDependency1, perBlockDependency1, perBlockDependency1);
    }
  }
}

Class diagram:

---
 config:
  class:
   hideEmptyMembersBox: true
---
classDiagram
	Service --|> IService
	Dependency --|> IDependency
	Dependency --|> IOtherDependency
	Dependency --|> IEnumerableᐸStringᐳ
	Composition ..> Service : IService MyService
	Service o-- "PerBlock" Dependency : Dependency
	Service o-- "PerBlock" Dependency : IDependency
	Service o-- "PerBlock" Dependency : IOtherDependency
	namespace Pure.DI.UsageTests.Basics.SimplifiedBindingScenario {
		class Composition {
		<<partial>>
		+IService MyService
		}
		class Dependency {
			+Dependency()
		}
		class IDependency {
			<<interface>>
		}
		class IOtherDependency {
			<<interface>>
		}
		class IService {
			<<interface>>
		}
		class Service {
			+Service(Dependency dependencyImpl, IDependency dependency, IOtherDependency otherDependency)
		}
	}
	namespace System.Collections.Generic {
		class IEnumerableᐸStringᐳ {
			<<interface>>
		}
	}
Loading