HowTo – NInject – Part 2 – Advanced Features

Source Code

All source code can be found on GitHub here.

My cheat sheet for NInject can be found here.

This is part of my HowTo in .NET seriies. An overview can be seen here,

This post is  a two part post on NInject:

  1. Basics
  2. Advanced Features

Bind To Constant

We can bind Interfaces and Classes to an actual instance or constant, a pseudo Singleton pattern.

var kernel = new StandardKernel();
var firstKnownC = new KnownC();

kernel.Bind<IClass>().ToConstant(firstKnownC);

var secondKnownC = kernel.Get<IClass>();

Assert.That (secondKnownC, Is.InstanceOf<IClass>());
Assert.That (secondKnownC, Is.InstanceOf<KnownC>());
Assert.That (secondKnownC, Is.SameAs(firstKnownC));

Bind to Constructor

We can bind to a delegate which returns a new instance

var kernel = new StandardKernel();
kernel.Bind<IClass>().ToConstructor( x => new KnownC());

var aClass = kernel.Get<IClass>();

Assert.That (aClass, Is.InstanceOf<IClass>());
Assert.That (aClass, Is.InstanceOf<KnownC>());

If we need to ask the kernel to resolve an instance it is passed into the method as the only parameter.

Bind<IMyService>().ToConstructor( ctorArg => new ClassC(ctorArg.Inject<IClassA>(), ctorArg.Inject<IClassB>()));

Bind To Method

Binds to a method; similar to a factory method.

var kernel = new StandardKernel();
kernel.Bind<IClass>().ToMethod(x => new KnownC());

var aClass = kernel.Get<IClass>();

If we need to ask the kernel for a resolution of a concrete instance:

Bind<IClass>().ToMethod( x => new ClassC(x.Kernel.Get<IClassA>(), x.Kernel.Get<IClassB>()));

Bind To Provider

Providers provide way to provide complex initiation.

var kernel = new StandardKernel();

kernel.Bind<IClass>().ToProvider( new KnownCProvider());

var aClass = kernel.Get<IClass>();

Assert.That(aClass, Is.InstanceOf<IClass>());
Assert.That(aClass, Is.InstanceOf<KnownC>());

public class KnownCProvider : Provider<KnownC>
{
	protected override KnownC CreateInstance(IContext context)
	{
		var aClass = new KnownC(); // We could do some complex initialisation here.
			return aClass;
	}
}

Contextual Binding

We can specify rules as to what class instance implementing an interface is injected into a class. This way we can provide logic for what is injected into a class based upon any inherited class (directly or indirectly inherited) or directly inherited.

WhenInjectedInto is determined as the ancestral class as any within the hierarchy.
WhenInjectedExactlyInto is determined as the immediate ancestral class only.

In the example below:

ChildA and ChildB both require an instance of IInject which is implemented by IInjectA and IInjectB, we can provide logic to determine which implementing instance of IInject is injected into the constructor of ChildA and ChildB.

InjectA is injected into ChildA because its parent ParentA inherits GrandParent and is bound with WhenInjectedInto.
InjectB is injected into ChildB because its parent is ParentB and is bound with WhenInjectedExactlyInto.

public class ParentA : GrandParent, IParent
{
	public ParentA ()
	{
	}
}

public class ChildA : ParentA, IChild
{
	public IInject Inject { get; set; }

	public ChildA ( IInject inject  )
	{
		Inject = inject;
	}
}

public class ChildB : ParentB, IChild
{
	public IInject Inject { get; set; }

	public ChildB ( IInject inject)
	{
		Inject = inject;
	}
}

var kernel = new StandardKernel ();

kernel.Bind<ChildA> ().ToSelf ();
kernel.Bind<ChildB> ().ToSelf ();
kernel.Bind<IInject> ().To<InjectA> ().WhenInjectedInto (typeof(GrandParent));
kernel.Bind<IInject> ().To<InjectB> ().WhenInjectedExactlyInto (typeof(ChildB));

var childA = kernel.Get<ChildA> ();
var childB = kernel.Get<ChildB> ();

Allow us to write our own attribute, tag classes with these attributes and provide conditional for injection around these attributes.

We can decorate parameters, methods/properties and classes with these attributes

The Target: Is considered a parameter Method or Constructor decorated.
The Member: Is a property decorated
The Class: Is a class decorated.

First we need to define our own parameters

[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = true, Inherited = true)]
public class WhenTargetHas : Attribute { }

[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = true, Inherited = true)]
public class WhenMemberHas : Attribute{ }

[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
public class WhenClassHas : Attribute { }

Then we decorate, Properties, Parameters and Classes with these attributes.

public class InjectWhenMemberAndTargetHas
{
	[Inject, WhenMemberHas]
	public IClass WhenMemberHas { get; set; }

	public IClass WhenTargetHas { get; set; }

	public InjectWhenMemberAndTargetHas([WhenTargetHas] IClass aClass)
	{
		WhenTargetHas = aClass;
	}
}

[WhenClassHas]
public class InjectWhenClassHas
{
	[Inject]
	public IClass WhenClassHas { get; set; }
}

Then we bind IClass to concrete types

var kernel = new StandardKernel ();

kernel.Bind<IClass>().To<KnownC>().WhenClassHas<WhenClassHas>();
kernel.Bind<IClass>().To<KnownD>().WhenTargetHas<WhenTargetHas>();
kernel.Bind<IClass>().To<KnownE>().WhenMemberHas<WhenMemberHas>();

Here we can conditionally bind IClass to KnownC,KnownD and KnownE such that we can control which class instance is injected into each entity.

InjectWhenClassHas has KnownC injected into the public property WhenClassHas as the class has the attribute [WhenClassHas] and the binding of IClass to KnownC WhenClassHas.

InjectWhenMemberAndTargetHas has KnownD injected into the constructor argument of IClass which is stamped with the attribute [WhenTargetHas] as we bind with WhenTargetHas.

InjectWhenMemberAndTargetHas has KnownE injected into the public property WhenMemberHas as the property is stamped with WhenMemberHas attribute and is bound to inject to KnownE when a property (or method) has the attribute.

Named binding provides a way to bind multiple instances to a entity by an arbitrary name and then to resolve the correct instance by providing the required name.

var kernel = new StandardKernel ();

kernel.Bind<IClass>().To<KnownC>().Named("NameknownC");
kernel.Bind<IClass>().To<KnownD>().Named("NameknownD");

KnownC classC = aKernel.Get<IClass>("NameknownC");
KnownD classD = aKernel.Get<IClass>("NameknownD");

Parameters can be stamped with the required binding name

public ClassC ( [Named("First") IClass aClass]
{}

With Meta Data or Attribute Based Helpers

Custom Attributes can contain conditional logic which allows the attribute to determine if a resolution should be made. Logic is made against tags and the values which are provided as part of the binding.

First we define an Attribute with logic

[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter,
                AllowMultiple = true, Inherited = true)]
public class IsSomething : ConstraintAttribute
{
	public override bool Matches (IBindingMetadata metadata)
	{
		return metadata.Has ("IsSomething") && metadata.Get<bool> ("IsSomething");
	}
}

[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter,
	                AllowMultiple = true, Inherited = true)]
	public class IsNotSomething : ConstraintAttribute
	{
		public override bool Matches (IBindingMetadata metadata)
		{
			return metadata.Has ("IsSomething") && !metadata.Get<bool> ("IsSomething");
		}
	}

We can then tag elements which require conditional injection

public class InjectWithIsSomething
{
	public IClass InjectedClass{ get; set; }

	public InjectWithIsSomething([IsSomething] IClass aClass)
	{
		InjectedClass = aClass;
	}
}

public class InjectWithIsNotSomething
	{
		public IClass InjectedClass{ get; set; }

		public InjectWithIsNotSomething([IsNotSomething] IClass aClass)
		{
			InjectedClass = aClass;
		}
	}

Both attributes provide logic for determining when they qualify based upon the expected values of IsSomething attribute. We assign the IsSomething value at bind time.

Bind<IClass> ().To<KnownC> ().WithMetadata ("IsSomething", true);
Bind<IClass> ().To<KnownD> ().WithMetadata ("IsSomething", false);

The resolve asks the attribute if the condition logic is met

var isSome =  kernel.Get<InjectWithIsSomething>();
var isNotSome =  kernel.Get<InjectWithIsNotSomething>();

In the example above we resolve IClass to either KnownC or KnownD based upon whether the parameter is decorated with [IsSomething] or [IsNotSomething] and the value to the IsSomething tag which is provided as part of binding.

Conditional Binding

We can also provide conditional logic by providing a delegate. In this case are asking the class its name and namespace.

Bind<IClass>().To<ClassA>().When(request => request.Target.Member.Name.StartsWith("ClassName"));
Bind<IClass>().To<ClassB>().When(request => request.Target.Type.Namespace.StartsWith("NameSpace.ClassName"));
Advertisements

HowTo – NInject – Part 1 – Basics

Source Code

All source code can be found on GitHub here.

My cheat sheet for NInject can be found here.

This is part of my HowTo in .NET seriies. An overview can be seen here,

This post is  a two part post on NInject:

  1. Basics
  2. Advanced Features

Intro

NInject is a dependency injection (DI) framework or inversion of control (IOC) framework.

In it’s simplest form it allows a way to register or ‘Bind’ a class which implements an interface against the interface and to resolve when required.

The Basics

The first requirement is a kernel.

IKernel aKernel = new StandardKernel();

We then bind an interface to a class.

aKernel.Bind<IClass>().To(AClass);

When we want an instance of IClass or AClass we ask the kernel for an instance of IClass.

AClass aClass = aKernel.Get<AClass>();

Classes are automatically bound to themselves. We can ask for an instance of them without binding to them.

BClass aClass = aKernel.Get<BClass>();

Resolvable and Non-Resolvable Classes

In the example above our class is presumed to have a parameterless constructor. NInject can actually resolve any constructor where all the parameters are resolvable.

A resolvable parameter is an entity which has a parameterless constructor or contains parameters which can all be resolved. This ruleset is cascaded all the way down the ‘call stack’ as far as required until there are no more parameters to resolve.

An interface parameter is resolvable if it has a binding.

A resolvable parameter can take on other forms; for example we can explicitly provide the parameters during bind time or resolve time.

Multiple Resolvable Constructors

When multiple resolvable constructors exists, the following ‘pecking’ order is used:

User defined constructor marked with [Inject] attribute
The constructor with the most known bound parameters.
The default parameterless constructor

Property & Method Injection

NInject will also inject properties and methods after an instance has been resolved. Methods and properties marked with the [Inject] attribute will all be called with any required parameters resolved.

[Inject]
public void InjectionMethod( KnownC c )
{
}

[Inject]
public KnownC InjectionProperty
{
}

Here an instance of KnownC will be injected into InjectionMethod and also InjectionProperty automatically before the kernel provides us with an instance of our resolved class.

Nested Resolves

Our cascade approach to resolving parameters also applies to Property and Method Injection.

In the example below our class Outter is resolved with an Instance of Middle injected into the property and constructor. Both instances of Middle is injected with Inner injected into both the Property and Constructor.

public class Outter
{
	[Inject]
	public Middle PropertyInject{ get; set; }

	public Middle ConstructorArgInject { get; set; }

	public Outter (Middle middle)
	{
		ConstructorArgInject = middle;
	}
}

public class Middle
{
	[Inject]
	public Inner PropertyInject{ get; set; }

	public Inner ConstructorArgInject { get; set; }

	public Middle (Inner middle)
	{
		ConstructorArgInject = middle;
	}
}

public class Inner
{
}

Constructor Arguments At Bind Time

We can provide parameters to constructor arguments at bind time. Parameters which are and are not resolvable can be provided. This is done with the WithConstructorArgument method and providing the name of the parameter ( which is case sensitive ) and also the value of the parameter to take.


var anKnownE = new KnownE ();

var kernel = new StandardKernel ();
kernel.Bind ()
	.ToSelf ()
		.WithConstructorArgument ("anInt", 1)
		.WithConstructorArgument ("aString", "Hello")
		.WithConstructorArgument ("aClass", anKnownE);

var aClass = kernel.Get ();

Constructor Arguments At Resolve Time

We can provide parameters to constructor arguments at resolve time. Parameters which are resolvable and also not resolvable can be provided. This is done by passing in an array of ConstructorArgument’s into the kernel’s Get method. The ConstructorArgument takes two parameters; the name of the parameter of our constructor parameter being resolved to and also the value; the parameter name is a string and is case sensitive.

var kernel = new StandardKernel ();
kernel.Bind ()
	.ToSelf ();

var aClass = kernel.Get (
	new [] {
	new ConstructorArgument ("anInt", 1),
	new ConstructorArgument ("aString", "Foo"),
	new ConstructorArgument ("aClass", new KnownD ())
}
);

Binding Scope

Binding scope allows determination of when a new instance of a class is provided and when an existing instance is provided.

InTransientScope: Will make the kernel always create a new instance when a class is resolved. This is the default action.

InSingletonScope: Only one instance is created per kernel instance. When subsequent resolves are made the existing instance, which was cached, is returned.

InRequestScope: Only one instance is created per kernel instance per web request instance.

InScope(Func): Provides a custom delegate to provide logic as to when a new instance is required or where the last instantiated instance is returned.

kernel.Bind().To<b>(ClassA).InTransientScope();
kernel.Bind().To<b>(ClassA).InSingletonScope();
kernel.Bind().To<b>(ClassA).InThreadScope();
kernel.Bind().To<b>(ClassA).InRequestScope();
kernel.Bind().To<b>(ClassA).InScope(x => DateTime.Now.day != x.DateCreated.day);

Kernel Modules

Kernel Modules provide a way of grouping and reusing binding registrations.

To create a kernel module inherit NinjectModule and place binding logic in Load().

OnLoad and OnUnLoad provide triggers for when a kernel module is unloaded from the kernel.

public class WarriorModule : NinjectModule
{
	// Binding code goes in here
	public override void Load()
	{
		Bind().ToSelf();

	}
	public override void OnLoad() { }   // OnLoad event
	public override void OnUnLoad() { } // OnUnload event
}

Kernel Modules can be passed into a kernel upon creation.

IKernel kernel = new StandardKernel(new AKernelModule());
IKernel kernel = new StandardKernel(new Module1(), new Module2(), ...);

NInject can use reflection to automatically load all kernel modules in a dll.

kernel.Load/UnLoad("*.dll"); // Load / Unload all Kernel Modules within dll

NInject can use reflection to automatically load all kernel modules in all dlls to be found within the current dlls domain.

kernel.Load.UnLoad(AppDomain.CurrentDomain.GetAssemblies());

Multiple Resoles

Where multiple classes are bound to the same interface, it is possible to resolve all of them in one hit.

var classes = kernel.GetAll();

These can also be injected in as an enumerable.

public AClass( IEnumerable classes)
{
}

Activation and Deactivation Trigger

We can register a delegate to be called when a resolved class is instantiated and disposed.

Bind().To<Class( ).OnActivation( x => x.ActivationMethod();
Bind().To<Class( ).OnDeactivation(x => x.DeactivationMethod());

Advanced Features

This concludes NInject Basics. More advanced features can be found here.

Day 11 – NInject

The Source Code

This post is part of my Dot Net On Linux posts. All the source code is available on GitHub here

Intro

NInject is a IOC framework for .Net and Mono. I had an initial investigation in a previous post here and also cheat sheet here.

I decided to do an API trawl to learn as much as possible about how to use the framework, the code associated with this post is my findings and the HowTo post can be found here and here.

The source code (see above) demonstrates examples of all functionality of the API which I can find, if you find anything missing please let me know!

NInject Cheat Sheet

A cheat sheet for Ninject IOC Frmaework in C#

All source code can be found on GitHub here.

This post is part of my cheat sheet series.

You can also view my HowTos  here and here


// **** DETERMINING WHICH CONSTRUCTOR TO USE ****
// The main DI pattern is Constructor Injection
// A known constructor parameter is one which has been explicitly bound
// An unknown constructor parameter is one which has not been explicitly bound even if it has a resolvable constructor the following order defines which constructor is used
// 1. User defined costructor marked with [Inject] attribute
// 2. The constructor with the most known bound parameters.
// 3. The default parameterless constructor

// **** PROPERTY / METHOD INJECTION
// Properties and methods marked with the [Inject] property will be resolved imediatly after the selected constructor
// Properties are required to be public set and private get
// Methods should be public and return void

[Inject]
public void AMethod(IClass aClass)
{
    this.aClass = aClass;
}

[Inject]
public IClass Property { private get; set; }

// **** BIND TO ****
// Classes are automatically bound to themselves
Bind<IClass>().ToSelf( )			// Explicit self binding
Bind<IClass>().To<Class>();  			// Bind to class
Bind<IClass>().ToConstant( )			// Binding with constant (the returned class), implicitly sets scope to InSingletonScope
Bind<IClass>().ToConstructor( )			// Bind with constructor
Bind<IClass>().ToMethod( )			// Binding with method
Bind<IClass>().ToProvider( )			// Binding with provider, class with parent of Provider<T> allowing addressing of complex initiation

// **** BINDING SCOPE ****
// The lifetime of an instance can be defined via the scope of the binding
// The default scope is InTransientScope
kernel.Bind<IClassA>().To<B>(ClassA).InTransientScope()  	// Always create an instance per Get call
kernel.Bind<IClassA>().To<B>(ClassA).InSingletonScope()		// Create only one instance
kernel.Bind<IClassA>().To<B>(ClassA).InThreadScope()		// Create one instance per thread and always return this
kernel.Bind<IClassA>().To<B>(ClassA).InRequestScope()		// Create one instance per web request and return this
kernel.Bind<IClassA>().To<B>(ClassA).InScope(Func<object>)	// Returns an object associated with the lifetime. The same instances is returned for the same life time of this associated lifetime object. Once this has been garbage collected our bound object will be recreated

// **** CONDITIONAL BINDING ****
Bind<IClass>().To<Class>().Named("AName");  				// Named Binding
Bind<IClass>().To<Class>().WithConstructorArgument("Iclass", delegat/object); // Constructor Argument
Bind<IClass>().To<Class>().WithMetadata("AMetaName", false); 		// Derrived Attribute Bindings
Bind<IClass>().To<Class>().WithParameter(new ConstructorArgument/Property("IClass/PropertyName", new XYZ() ); // WithConstructorArgument is a short cut to this
Bind<IClass>().To<Class>().WithPropertyValue(ProprtyName, delegate/object); // Explicit property injection
Bind<IClass>().To<Class>().When();					// Explicit Conditional binding
Bind<IClass>().To<Class>().WhenAnyAnchestorNamed("AnyParentInAncestry"); // When any class in ancestry is named
Bind<IClass>().To<Class>().WhenClassHas<AnAttribute>();  		// Binding with attributes based helpers
Bind<IClass>().To<Class>().WhenInjectedInto(typeof(AClass)); 		// Conditional injected into AClass or any derrived classes
Bind<IClass>().To<Class>().WhenInjectedExactlyInto(typeof(AClass));	// Conditional injected into AClass and not any derrived classes
Bind<IClass>().To<Class>().WhenMemberHas<AnAttribute>();  		// Binding with attributes based helpers
Bind<IClass>().To<Class>().WhenParentNamed("ParentName");		// Bind when the direct parent is named
Bind<IClass>().To<Class>().WhenTargerHas<AnAttribute>(); 		// Binding with attributes based helpers

// **** MULTIPLE BINDING WITH BindingConfiguration ****
// Default bind up to 4 however more can be found via caching and provinding the bind config.
var bindingConfiguration =
    Bind<IInterface1, IInterface2, IInterface3, IInterface4>()
        .To<Implementation>()
        .BindingConfiguration;
kernel.AddBinding(new Binding(typeof(IInterface5), bindingConfiguration));
kernel.AddBinding(new Binding(typeof(IInterface6), bindingConfiguration));

// **** OnActivation AND OnDeactivation EVENTS
// Trigger evets on the activation and deactivation
Bind<IClass>().To<Class( ).OnActivation( x => x.ActivationMethod())		// Called when an object is activate (instantiated)
Bind<IClass>().To<Class( ).OnDeactivation(x => x.DeactivationMethod())		// Called when an object is deactivate (disposed?)

// **** KERNEL CREATION ****
IKernel kernel = new StandardKernel();

// *** KERNEL MODULES ***
// Provide a grouping of registring bindings
public class WarriorModule : NinjectModule
{
    public override void Load() { } 	// Binding code goes in here
    public override void OnLoad() { } 	// OnLoad event
    public override void OnUnLoad() { } // OnUnload event
}

IKernel kernel = new StandardKernel(new AKernelModule());
IKernel kernel = new StandardKernel(new Module1(), new Module2(), ...);
kernel.Load/UnLoad("*.dll"); // Load / Unload all Kernel Modules within dll
kernel.Load.UnLoad(AppDomain.CurrentDomain.GetAssemblies()); // // Load / Unload all Kernel Modules within the current domains dll's

// **** GET / RESOLVE / INJECT ****
// During execution of code request instance of injected class via the kerel
// Any classes passed in as parameters to the constructor or INJECT marked methods/properties will be automatically resolved.
var aClass = kernel.Get<IClass>();
var classes = kernel.Get<IWarrior>( new ConstructorArgument( "IClass", new AClass() ) );
var classes = kernel.GetAll<IClass>();

// **** MULTIPLE BINDINGS
public ClassName( IEnumerable<IClass> classes) // An instance off all classes implementing the interface will be injected in

// **** NAMED BINDING ****
Bind<IClass>().To<ClassA>().Named("First"); 	// Name the binding during binding
Bind<IClass>().To<ClassB>().Named("Second");
kernel.Get<IClass>("First"); 			// Resolve the bind by providing the name
public ClassC ( [Named("First") IClass aClass]  // Consuctors, Methods and Properties can have named parameters to resolve their injection

// **** DERRIVED ATTRIBUTE BINDINGS ****
// Define an attribute
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = true, Inherited = true)]
public class IsSomething : ConstraintAttribute {
    public bool Matches(IBindingMetadata metadata) {
        return metadata.Has("IsSomething") && metadata.Get<bool>("IsSomething");
    }
}

Bind<IClass>().To<AClass>().WithMetadata("IsSomething", false);
Bind<IClass>().To<BClass>().WithMetadata("IsSomething", true);

public AnotherClass([IsSomething] IClass aClass) {} // face resolves to BClass

// TODO: try this bit
kernel.Get<IClass>(metadata => metadata.Has("IsSomething") && metadata.Get<bool>("IsSomething") == false ) // resolves to AClass

// **** BINDING WITH ATTRIBUTE BASED HELPERS ****
// The Target: the parameter being injected into
// The Member: the property, method or constructor itself
// The Class: the class Type within which the Member or Target is defined within

[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
public class WhenClassHas : Attribute{ }

[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = true, Inherited = true)]
public class WhenMemberHas : Attribute{}

[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = true, Inherited = true)]
public class WhenTargetHas : Attribute{}

public class InjectWhenMemberAndTargetHas
{
	[Inject, WhenMemberHas]
	public IClass WhenMemberHas { get; set; } // Member has an attribute
	public IClass WhenTargetHas { get; set; }
	public InjectWhenMemberAndTargetHas([WhenTargetHas] IClass aClass){WhenTargetHas = aClass;} // target has an attribute
}

[WhenClassHas]
public class InjectWhenClassHas
{
	[Inject] // Class is marked with attriibute. binding is done by class
	public IClass WhenClassHas { get; set; }
}

Bind<IClass>().To<KnownC>().WhenClassHas<WhenClassHas>();
Bind<IClass>().To<KnownD>().WhenTargetHas<WhenTargetHas>();
Bind<IClass>().To<KnownE>().WhenMemberHas<WhenMemberHas>();

// **** BIND WITH METHOD ****
// Used to bind to factory methods.
// Here we are passing in the reques5 context tyoe
Bind<IClass>().ToMethod( context => AFactory.Create( context.Request.Target.Type ) )
Bind<IClass>().ToMethod( x => new ClassC(x.Kernel.Get<IClassA>(), x.Kernel.Get<IClassB>()));

// **** BIND TO PROVIDER ****
// Binding with provider, class with parent of Provider<T> allowing addressing of complex initiation
Bind<IClass>().ToProvider(new AProvider())

public class AProvider : Provider<AClass>
{
    protected override AClass CreateInstance(IContext context)
    {
        return new AClass(); // Do some complex initialization here.
    }
}

// **** BIND TO CONSTRUCTOR ****
Bind<IMyService>().ToConstructor( ctorArg => new ClassC(ctorArg.Inject<IClassA>(), ctorArg.Inject<IClassB>())); // TODO what is the difference between constructor and method binding

// **** BIND WITH CONSTRUCTOR ARGUMENT ****
Bind<IClass>().To<Class>().WithConstructorArgument("ParameterName", x =>x.Kernel.Get<IClass>()); //

// **** BIND WITH EXPLICIT CONDITIONAL BINDING ****
Bind<IClass>().To<ClassA>().When(request => request.Target.Member.Name.StartsWith("ClassName"));
Bind<IClass>().To<ClassB>().When(request => request.Target.Type.Namespace.StartsWith("NameSpace.ClassName"));

NUnit Cheat Sheet

A cheat sheet for the NUnit test framework

All source code can be found on GitHub here.

This post is part of my cheat sheet series.

 

using System;
using System.Reflection;
using System.IO;
using System.Text;
using System.Collections;
using System.Collections.Generic;
using NUnit.Framework;

namespace NUnitCheatSheet
{
	/// <summary>
	/// TestFixtureSetUp: Provides a config class for setting up and tearing down the test fixture.
	/// Provides the config for all TestFixture classes witin the same namespace.
	/// </summary>
	[SetUpFixture]
  	public class TestFixtureSetUp
  	{
		/// <summary>
		/// SetUp; run once before all tests in a test fixture.
		/// Run once for each TestFixture in the same namespace.
		/// </summary>
	    [SetUp]
		public void RunBeforeAnyTests()
		{
		  // Set up code here.
		}
		/// <summary>
		/// TearDown; run once after all tests in a test fixture.
		/// Run once for each TestFixture in the same namespace.
		/// </summary>
	    [TearDown]
		public void RunAfterAnyTests()
		{
		  // Clear up code here.
		}
  	}

	/// <summary>
	/// Factory class for providing test data for tests with the TestCaseSource attribue.
	/// </summary>
	public class TestCaseDataFactory
	{
		/// <summary>
		/// TestCaseSource tests can consume IEnumerable properties which return TestCaseData
		/// </summary>
	  	public static IEnumerable TestCasesDataForTestCaseSourceTest
		{
		    get
		    {
		      yield return new TestCaseData( 1, "1" ).Returns( 2 ); // Defines the test data and the expected return
		      yield return new TestCaseData( 2, "2" ).Returns( 4 );
		      yield return new TestCaseData( 0, "a" )
						.Throws(typeof(ArgumentException)); // Defines the test data and the expected throw exception
		    }
		}
	}

	/// <summary>
	/// TestFixture defines a class of tests
	/// </summary>
	[TestFixture(), Category("MyTests"), Description("NUnut Cheat Sheet!")]
	public class Test
	{
		/// <summary>
		/// TestCaseSource attributes can use static properties to return an array of test data
		/// </summary>
		public static object[] CaseSourceTestData =
		{
		    new object[] { 1, 1.1m, "2.1" },
			new object[] { 2, 2.2m, "4.2" },
			new object[] { 3, 3.3m, "6.3" },
		};

		# region Setup and Tear Down
		/// <summary>
		/// TestFixtureSetUp called once before any tests have been run in the same TestFixture
		/// </summary>
		[TestFixtureSetUp] public void FixtureSetUp()
    	{
			// Set up code here.
		}
		/// <summary>
		/// TestFixtureTearDown called once after all tests have been run in the same TestFixture
		/// </summary>
    	[TestFixtureTearDown] public void FixtureTearDown()
    	{
			// Clear up code here.
		}

		/// <summary>
		/// SetsUp is called once before each Test within the same TestFxiture
		/// </summary>
		[SetUp] public void SetUp()
    	{
			// Set up code here.
			// If this throws an exception no Test in the TestFixture are run.
		}

		/// <summary>
		/// TearsDown is called once after each Test within the same TestFixture.
		/// </summary>
    	[TearDown] public void TearDown()
    	{
			 // Clear up code here.
			// Will not run if no tess are run due to [SetUp] throwing an exception
		}
		# endregion

		/// <summary>
		/// ExpectedException defines what exception and how it is configured
		/// </summary>
		[Test, ExpectedException( typeof(Exception), ExpectedMessage = "Foo", MatchType = MessageMatch.Exact)]
		public void ExpectedExceptionAttributeTest()
		{
			// MessageMatch is an enum of: Contains, Exact, Regex, StartsWith
			throw new Exception("Foo");
		}

		/// <summary>
		/// Explicit defines tests which are only run manualy.
		/// </summary>
		[Test, Explicit("Test has to be run explicitly")]
    	public void ExplicitAttributeTest()
    	{
		}

		/// <summary>
		/// Ignore marks tests which are not run even if run manually
		/// </summary>
		[Test, Ignore("Ignore this test")]
    	public void IgnoreAttribueTest()
    	{
		}

		/// <summary>
		/// MaxTimeAttribute defines the max run time in milliseconds before the test is considered as failed but allowed to complete.
		/// </summary>
		[Test, MaxTimeAttribute(2000)]
		public void MaxtimeAttributeTest()
		{
		}

		/// <summary>
		/// Timeout defines the max run time in milliseconds before the test is automatically failed.
		/// Can be used on TestFixture to set for each contained Test's
		/// </summary>
		[Test, Timeout(200)]
		public void TimeOutTest()
		{
		}

		/// <summary>
		///
		/// </summary>
		[Test, Platform("Mono"), Culture("en-GB")]
		public void PlatformAttributeTest()
  		{
			// Can also provide exclusion culture and platform
			// Test case is ignored if Platform or Cultrue can not be provided
 		}

		/// <summary>t
		/// Property: categorises the test witin the test output XML.
		/// </summary>
		[Test, Property("PropertyName", "Value")]
		public void PropertyAttributeTest()
    	{}

		/// <summary>
		/// Custom Property: categorises the test within the test output XML.
		/// </summary>
		[Test, CustomPropertyAttribute(CustomPropertyValue.One)]
		public void CustomPropertyAttributeTest()
    	{}

		#region Parameterized
		/// <summary>
		/// Combinatorial: The test is run with each combination of Values for each parameter
		/// </summary>

		[Test, Combinatorial]
		public void CombinatorialAttributeTest ([Values(1,2,3)] int a, [Values("a", "b", "c")] string b)
		{
			// Called 9 times with  parameter pairs of: {1,a}, {1,b}, {1,c}, {2,a}, {3,b}....
		}

		/// <summary>
		/// Random: Test can be run with a random value. Random(Min,Max,Count)
		/// </summary>
		[Test]
		public void RandomAttributeTest(
    	[Random(1, 10, 2)] int value)
		{
			// Called 2 times with a random integer between 1 and 10
			Assert.That(value, Is.InRange(1,10));
		}

		/// <summary>
		/// Sequential: Parameters with values are run in sequence
		/// </summary>
		[Test, Sequential]
		public void SequentialAttributeTest(
    	[Values(1,2,3)] int x,
    	[Values("A","B")] string s)
		{
			// Test runs for parameter pairs {1,A}, {2,B}, {3, null}
		}

		/// <summary>
		/// Range: Parameter is run with a sequence of values incremented. Range(Min,Max,Increment).
		/// </summary>
		[Test]
		public void RangeAttributeTest(
    	[Range(0.0, 1, 0.5)] decimal value)
		{
			// Test run for parameters, 0.0, 0.5, 1.0
			Assert.That(value, Is.InRange(0m,1m));
		}

		/// <summary>
		/// TestCaseSource: referencing a public property which privides a sequence of test data
		/// </summary>
		[Test, TestCaseSource("CaseSourceTestData")]
		public void CaseSourceTest(int a, decimal b, string c)
		{
			// Can also specify the class to which the property is found upon.
			Assert.That(a + b, Is.EqualTo(Decimal.Parse(c)));
		}

		/// <summary>
		/// TestCaseSource: referncing a class and property which provides a sequence of test data and expected output.
		/// </summary>
		[Test,TestCaseSource(typeof(TestCaseDataFactory),"TestCasesDataForTestCaseSourceTest")]
		public decimal TestCaseSourceTest(int a, string b)
		{
			int bInt;
			if( !int.TryParse(b, out bInt))
				throw new ArgumentException(string.Format("Can not parse '{0}' to an integer", b), "b");

			return a + bInt;
		}

		/// <summary>
		/// TestCase: provides a test input data and expected result.
		/// </summary>
		[TestCase(1,1, Result=2)]
		[TestCase(2,2, Result=4)]
		[TestCase(3,3, Result=6)]
		public int TestCaseTest(int a, int b)
		{
		  return( a + b);
		}
		#endregion

		/// <summary>
		/// Assertion Based Test
		/// </summary>
		[Test(), Category("Assertion based testing")]
		public void TestAssertions ()
		{

			// Equality
			Assert.AreEqual (true, true);
			Assert.AreNotEqual (true, false);

			// Identity
			Assert.AreSame (string.Empty, string.Empty);
			Assert.AreNotSame (new object (), new object ());
			Assert.Contains (string.Empty, new List<object> (){string.Empty});

			// Condition
			Assert.IsTrue (true);
			Assert.IsFalse (false);
			Assert.IsNull (null);
			Assert.IsNaN (Double.NaN);
			Assert.IsEmpty (new List<object> ());
			Assert.IsEmpty (new List<object> ());
			Assert.IsNotEmpty (new List<object> (){1});
			Assert.IsNotEmpty ("Foo");

			// Comparision
			Assert.Greater (Decimal.MaxValue, Decimal.MinValue);
			Assert.GreaterOrEqual (Decimal.MinValue, Decimal.MinValue);
			Assert.Less (Decimal.MinValue, Decimal.MaxValue);
			Assert.LessOrEqual (Decimal.MinValue, Decimal.MinValue);

			// Types
			Assert.IsInstanceOf<decimal> (decimal.MinValue);
			Assert.IsNotInstanceOf<int> (decimal.MinValue);
			Assert.IsNotAssignableFrom (typeof(List<Type>), string.Empty);        	// Equivalent to Type.IsAssignableFrom Method
			Assert.IsAssignableFrom (typeof(List<decimal>), new List<decimal> ()); 	// http://msdn.microsoft.com/en-gb/library/system.type.isassignablefrom.aspx
			Assert.IsNotAssignableFrom<List<Type>> (string.Empty);
			Assert.IsAssignableFrom<List<decimal>> (new List<decimal> ());

			// Exceptions
			Assert.Throws (typeof(ArgumentNullException), () => {
				throw new ArgumentNullException (); }
			);

			Assert.Throws<ArgumentNullException> (() => {
				throw new ArgumentNullException (); }
			);

			Assert.DoesNotThrow (() => { });

			Assert.Catch (typeof(Exception), () => {
				throw new ArgumentNullException (); }
			);

			Assert.Catch<Exception> (() => { // Similar as Throws but allows any derrived class of the thrown exception
				throw new ArgumentNullException (); }
			);

			// Strings
			StringAssert.Contains ("Foo", "MooFooMoo");
			StringAssert.StartsWith ("Foo", "FooMoo");
			StringAssert.EndsWith ("Moo", "FooMoo");
			StringAssert.AreEqualIgnoringCase ("FOO", "foo");
			StringAssert.IsMatch ("[0-9]", "1");

			// Collections
			CollectionAssert.AllItemsAreInstancesOfType (new List<decimal> (){ 0m }, typeof(decimal));
			CollectionAssert.AllItemsAreNotNull (new List<decimal> (){ 0m });
			CollectionAssert.AllItemsAreUnique (new List<decimal> (){ 0m, 1m });
			CollectionAssert.AreEqual (new List<decimal> (){ 0m }, new List<decimal> (){ 0m });
			CollectionAssert.AreEquivalent (new List<decimal> (){ 0m, 1m }, new List<decimal> (){ 1m, 0m }); // Same as AreEqual though order does not mater
			CollectionAssert.AreNotEqual (new List<decimal> (){ 0m }, new List<decimal> (){ 1m });
			CollectionAssert.AreNotEquivalent (new List<decimal> (){ 0m, 1m }, new List<decimal> (){ 1m, 2m });  // Same as AreNotEqual though order does not matter
			CollectionAssert.Contains (new List<decimal> (){ 0m, 1m }, 1m);
			CollectionAssert.DoesNotContain (new List<decimal> (){ 0m, 1m }, 2m);
			CollectionAssert.IsSubsetOf (new List<decimal> (){ 1m }, new List<decimal> (){ 0m, 1m }); // {1} is considered a SubSet of {1,2}
			CollectionAssert.IsNotSubsetOf (new List<decimal> (){ 1m, 2m }, new List<decimal> (){ 0m, 1m });
			CollectionAssert.IsEmpty (new List<decimal> (){ });
			CollectionAssert.IsNotEmpty (new List<decimal> (){ 1m });
			CollectionAssert.IsOrdered (new List<decimal> (){ 1m, 2m, 3m });
			CollectionAssert.IsOrdered (new List<string> (){ "a", "A", "b"}, StringComparer.CurrentCultureIgnoreCase);
			CollectionAssert.IsOrdered (new List<int> (){ 3,2,1}, new ReverseComparer()); // Only supports ICompare and not ICompare<T> as of version 2.6

			//  File Assert: various ways to compare a stream or file.
			FileAssert.AreEqual (new MemoryStream (), new MemoryStream ());
			FileAssert.AreEqual (new FileInfo ("MyFile.txt"), new FileInfo ("MyFile.txt"));
			FileAssert.AreEqual ("MyFile.txt", "MyFile.txt");
			FileAssert.AreNotEqual (new FileInfo ("MyFile.txt"), new FileInfo ("MyFile2.txt"));
			FileAssert.AreNotEqual ("MyFile.txt", "MyFile2.txt");
			FileAssert.AreNotEqual (new FileStream ("MyFile.txt", FileMode.Open), new FileStream ("MyFile2.txt", FileMode.Open));

			// Utilities: will cause the test to stop immediatly and mark the test as:
			Assert.Pass ();
			Assert.Fail ();
			Assert.Ignore ();
			Assert.Inconclusive ();

			// Defining the failed message
			Assert.IsTrue(true, "A failed message here"); // also object[] params can be defined
		}

		/// <summary>
		/// Constraint based testing: Test cases with a fluent design pattern
		/// </summary>
		[Test()]
		[Category("Constraint based testing")]
		public void TestConstraints ()
		{

			// Numerical Equality
			Assert.That (1, Is.EqualTo (1));
			Assert.That (1, Is.Not.EqualTo (2));
			Assert.That (1.1, Is.EqualTo (1.2).Within (0.1)); // Allow a tollerance
			Assert.That (1.1, Is.EqualTo (1.01).Within (10).Percent); // Pass tollerance within percent

			// Float Equality
			Assert.That (20000000000000004.0, Is.EqualTo (20000000000000000.0).Within (1).Ulps); // Pass tollerance with units of last place

			// String Equality
			Assert.That ("Foo!", Is.EqualTo ("Foo!"));
			Assert.That ("Foo!", Is.Not.EqualTo ("FOO!"));
			Assert.That ("Foo!", Is.EqualTo ("FOO!").IgnoreCase);
			Assert.That (new List<string> (){ "FOO!"}, Is.EqualTo (new List<string> (){ "Foo!"}).IgnoreCase);

			// Date, Time and TimeSpan equality
			Assert.That (DateTime.Today, Is.EqualTo (DateTime.Today));
			Assert.That (DateTime.Now, Is.Not.EqualTo (DateTime.Now));
			Assert.That (DateTime.Now, Is.EqualTo (DateTime.Now).Within (TimeSpan.FromSeconds (1))); // Time based pass tollerances
			Assert.That (DateTime.Now, Is.EqualTo (DateTime.Now).Within (1).Days);
			Assert.That (DateTime.Now, Is.EqualTo (DateTime.Now).Within (1).Hours);
			Assert.That (DateTime.Now, Is.EqualTo (DateTime.Now).Within (1).Minutes);
			Assert.That (DateTime.Now, Is.EqualTo (DateTime.Now).Within (1).Seconds);
			Assert.That (DateTime.Now, Is.EqualTo (DateTime.Now).Within (1).Milliseconds);

			// Collection equality
			Assert.That (new double[] {1.0,2.0,3.0}, Is.EqualTo (new int[] {1,2,3}));
			Assert.That (new double[] {1.0,2.0,3.0}, Is.Not.EqualTo (new int[] {1,2,3, 4}));
			Assert.That (new double[] {1.0,2.0,3.0,4.0}, Is.EqualTo (new  int[,] {{1,2}, {3,4}}).AsCollection); // Compare data and not collection (flattens a collection of collections)

			// Customer Comparer
			Assert.That( int.MinValue, Is.EqualTo(int.MaxValue).Using(new WhoCaresComparer()));

			// Identity (Same instance of)
			Assert.That( string.Empty, Is.SameAs(string.Empty));
			Assert.That( new object(), Is.Not.SameAs(new object()));

			// Condition
			Assert.That( string.Empty, Is.Not.Null);
			Assert.That( true, Is.True);
			Assert.That( true, Is.Not.False);
			Assert.That( double.NaN, Is.NaN);
			Assert.That( string.Empty, Is.Empty);
			Assert.That( new List<int>(), Is.Empty);
			Assert.That( new List<int>(){1,2,3}, Is.Unique);

			// Comparision
			Assert.That(1, Is.LessThan(2));
			Assert.That(1, Is.GreaterThan(0));
			Assert.That(1, Is.LessThanOrEqualTo(1));
			Assert.That(1, Is.GreaterThanOrEqualTo(1));
			Assert.That(1, Is.AtLeast(0));	// Same as GreaterThanOrEqualTo
			Assert.That(1, Is.AtMost(2)); 	// Same as LessThanOrEqualTo
			Assert.That(1, Is.InRange(1,2));

			// Path: comparision on file path only without comparing the contents.
			// All paths are converted to 'canonical' path before comparing; full direct path to file.
			Assert.That( "MyFile.txt", Is.SamePath("MyFile.txt"));
			Assert.That( "MyFile.txt", Is.SamePath( "MYFILE.TXT" ).IgnoreCase );
			Assert.That( "MyFile.txt", Is.SamePath("MyFile.txt").RespectCase);
			Assert.That( "/usr/bin", Is.SubPath("/usr"));			// directory exists within another
			Assert.That( "/usr/bin", Is.SamePathOrUnder("/usr"));	// SamePath or SubPath

			// Type Constraints
			Assert.That(new MemoryStream(), Is.InstanceOf(typeof(Stream)));  // Is type or ancestor
			Assert.That(new MemoryStream(), Is.TypeOf(typeof(MemoryStream))); // Is type and not ancestor
			Assert.That(new object(), Is.AssignableFrom(typeof(MemoryStream))); // Can be assigned from
			Assert.That(new MemoryStream(), Is.AssignableTo(typeof(Stream))); // Can be assignable to

			Assert.That(new MemoryStream(), Is.InstanceOf<Stream>());  // Is type or ancestor
			Assert.That(new MemoryStream(), Is.TypeOf<MemoryStream>()); // Is type and not ancestor
			Assert.That(new object(), Is.AssignableFrom<MemoryStream>()); // Can be assigned from
			Assert.That(new MemoryStream(), Is.AssignableTo<Stream>()); // Can be assignable to

			// String Comparision
			Assert.That( "Foo", Is.StringContaining( "o" ) );
			Assert.That( "Foo", Is.StringContaining( "O" ).IgnoreCase );
			Assert.That( "Foo", Is.StringStarting( "F" ) );
			Assert.That( "Foo", Is.StringEnding( "o" ) );
			Assert.That( "Foo", Is.StringMatching( "^[F]" ) ); // Regular ecpression match

			// Collection Comparison
			Assert.That( new List<int>(){1,2,3}, Has.All.GreaterThan(0) );
			Assert.That( new List<int>(){1,2,3}, Is.All.GreaterThan(0) );
			Assert.That( new List<int>(){1,2,3}, Has.None.GreaterThan(4));
			Assert.That( new List<int>(){1,2,3}, Has.Some.GreaterThan(2));
			Assert.That( new List<int>(){1,2,3}, Has.Count.EqualTo(3));
			Assert.That( new List<int>(){1,2,3}, Is.Unique);
			Assert.That( new List<int>(){1,2,3}, Has.Member(1));  // Contains
			Assert.That( new List<int>(){1,2,3}, Is.EquivalentTo( new List<int>(){3,2,1})); // Same data without carring about the order
			Assert.That( new List<int>(){1,2,}, Is.SubsetOf( new List<int>(){3,2,1})); // All are cotained.

			// Property Constraint
			Assert.That( new List<int>(), Has.Property("Count").EqualTo(0));  // Checks public property
			Assert.That( new List<int>(), Has.Count.EqualTo(0));			  // Same as Has.Property("Count").EqualTo(0)
			Assert.That( string.Empty, Has.Length.EqualTo(0));				  // Same as Has.Property("Length").EqualTo(0)
			Assert.That ( new Exception("Foo"), Has.Message.EqualTo("Foo"));  // Exception has message
			Assert.That ( new Exception("Foo", new ArgumentException("Moo")), // Inner exception is of type and has message
			             Has.InnerException.InstanceOf<ArgumentException>().And.InnerException.Message.EqualTo("Moo"));

			// Throws Constraint
			// See also Property constrains for Message and Inner Exception
			// Throws.Exception allow AND, Throws.InstanceOf<> is short hand
			Assert.That (() => { throw new ArgumentException("Foo"); },
				Throws.Exception.InstanceOf<ArgumentException>().And.Message.EqualTo("Foo"));

			Assert.That (() => { throw new ArgumentNullException("Foo"); },
				Throws.Exception.TypeOf<ArgumentNullException>());

			Assert.That (() => { throw new ArgumentNullException("Foo"); },
				Throws.InstanceOf<ArgumentNullException>());

			Assert.That (() => { }, Throws.Nothing);

			Assert.That (() => { throw new Exception("Foo", new ArgumentException("Moo"));},
				Throws.Exception.Message.EqualTo("Foo").And.InnerException.InstanceOf<ArgumentException>());

			Assert.That (() => { throw new ArgumentException(); }, Throws.ArgumentException);

			// Compound Constraints
			Assert.That( 2, Is.Not.EqualTo( 1 ));
			Assert.That( new List<int>(){ 1, 2, 3 }, Is.All.GreaterThan( 0 ) );

			Assert.That( 1, Is.GreaterThan( 0 ).And.LessThan( 2 ) );  // .And amd & are the same
			Assert.That( 1, Is.GreaterThan( 0 ) & Is.LessThan( 2 ) );

			Assert.That( 1, Is.LessThan( 10 ) | Is.GreaterThan( 0 ) ); // .Or and | are the same
			Assert.That( 1, Is.LessThan( 10 ).Or.GreaterThan( 0 ) );

			// Delayed
			Assert.That(() => { return true;}, Is.True.After(10));		// Passes after x time
			Assert.That(() => { return true;}, Is.True.After(10, 10));	// Passes after x time and polling..

			// List Mapper
			Assert.That(List.Map(new List<string>(){"1", "22", "333"}).Property("Length"),  // Allows all elememts in a list to have a condition provided for them
			            Is.EqualTo(new List<int>(){1,2,3}));
		}
	}
	# region Elements consumed by the tests above
	public class WhoCaresComparer : IEqualityComparer<int>
	{
	    public bool Equals(int b1, int b2)
	    {
			return true;
	    }

	    public int GetHashCode(int aNumber)
	    {
			return aNumber.GetHashCode();
	    }
	}

	public class ReverseComparer : IComparer
	{
		public int Compare (object a, object b)
		{
			return ((int)b).CompareTo((int)a);
		}
	}

	public enum CustomPropertyValue
	{
    	One,
    	Two,
   	}

	[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
	public class CustomPropertyAttribute : PropertyAttribute
	{
    	public CustomPropertyAttribute( CustomPropertyValue value ) : base( "Custom", value.ToString() )
		{
		}
	}
	#endregion
}

Day 3 – Dot NET on Linux – Dependency Injection with Ninject

Intro

Dependency injection along with Moc Frameworks are becoming  increasingly popular. They allow decoupling of parts of the system to allow them to be substituted easily during runtime. This is especially powerful when the item being substituted is an expensive entity which is hard to consume during unit testing.

The Source Code

This post is part of my Dot Net On Linux posts. All the source the source code from the series of posts is available on GitHub here

What is Dependency Injection?

DI for short is a control mechanism which allows us to satisfy the Dependency Inversion Principle of the SOLID Design Principles.

By dictating to lower level components what other lower level components are to be used we can uncouple parts of a system to allow them to be independently replaced. This is done by injecting concrete class implementations into classes which are expecting abstractions.

DI is the principle which also allows us to inject mock implementation of components which are expensive or hard to consume while unit testing. This can allow us to unit test without a database or 3rd party web services. This can allow a greater coverage of unit testing and also allowing unit testing to be run quicker meaning there is more chance they will be run.

Ninject

Ninject is a DI framework which is commonly used. What it lacks comparing to other DI frameworks it makes up in its simplicity.

The Source Code

All the source code from the series of posts is available on GitHub here.

Installation

wget http://ninject2.googlecode.com/files/Ninject-3.0.0.15-release-mono-2.0.zip
mkdir Ninject
mv Ninject-3.0.0.15-release-mono-2.0.zip Ninject
cd Ninject
unzip Ninject-3.0.0.15-release-mono-2.0.zip

Adding Ninject References

To add Ninject into a  project; highlight the project within the solution tree then from the Project menu “Project –> Edit References”.

From the “Edit References” dialog box select the .Net Assembly tab. Navigate to the unzipped Ninject directory and highlight Ninject.dll. Select the add button and then ok.

Ninject can then be imported into a class with “using Ninject”

The code

The most common occurrence of DI injection are

  • Resolve concrete class from abstract interface
  • Resolve concrete class with dependence of constructor DI
  • Resolve concrete class from abstract interface with configured constructor arguments
  • Conditionally resolve concrete class from abstract interface when injected into a child class

Resolve concrete class from abstract interface

The most common form of injection requires resolving a concrete implementation of a class when referencing its interface abstraction.
At an initial point in our application run time we create an instance of the DI kernel and register our required concrete class against our interface. Later on when we want to use the class via its abstraction we ask the DI kernel to resolve this from its abstract interface and provide us with an instance.


// The DI Kernel
var kernelInstance = new StandardKernel ();

// Bind our concre
kernelInstance.Bind().To (typeof(SimpleClass));

// Retrieval of a concrete implementation of our interface
var myClass = kernel.Get();

Resolve concrete class with dependence of constructor DI

If any constructor or class being resolved requires arguments these can be automatically passed in upon creation. As long as we have a parameterless constructor for the argument all this can happen automatically.


// Constructor of class being resolved by the DI kernel
public ClassWithDependancy (ISimpleClass simpleClass)
{
    this.SimpleClass = simpleClass;
}

// The DI Kernel
var kernelInstance = new StandardKernel ();

// Bind our concrete classes to abstractions
kernelInstance.Bind().To (typeof(SimpleClass));
kernelInstance.Bind().To (typeof(ClassWithDependancy));

// Retrieval of a concrete implementation of our interface
var myClass = kernel.Get();

Resolve concrete class from abstract interface with configured constructor arguments

An injection with parameters in the constructor is also catered for.

kernel.Bind().To (typeof(ClassWithConstructorParameters)).
WithConstructorArgument ("messageOne", "Hello").
WithConstructorArgument ("messageTwo", "There");

Conditionally resolve concrete class from abstract interface when injected into a child class

If two classes implement the same interface we can conditional config which is injected into an implementing classes constructor.

kernel.Bind().To().WhenInjectedInto();