Showing posts with label Design Patterns. Show all posts
Showing posts with label Design Patterns. Show all posts

Sunday, September 12, 2010

A Repository-like façade for Entity Framework – Part II

This is the second post in this series.

The first thing we need to do to enable using our POCOs with EF 4.0 is to decide how we want to handle change tracking and lazy loading of our child collections.

For now, let’s take full advantage of EF’s capabilities and allow it to generate the proxies for lazy loading and full change tracking.

To do this, there are four requirements:

  1. Each POCO must have an empty default constructor.
  2. Each property of the POCO must be declared virtual.
  3. The child collection properties must be of type ICollection<T>.
  4. New POCO objects must be instantiated with ObjectContext.CreateObject<T>.

Since List<T> is an implementation of ICollection<T>, we can keep it for our collection, but we need to mark all the properties as virtual. Here are our entities:

using System.Collections.Generic;

namespace Entities.School
{
public class Department
{
public virtual long Id { get; set; }

public virtual string Name { get; set; }

public virtual List<Course> Courses { get; set; }
}

public class Course
{
public virtual long Id { get; set; }

public virtual string Name { get; set; }

public virtual Department Department { set; get; }
}
}



Note that I have removed the code that kept the Department.Courses collection in sync, when the Course.Department is set. I had hoped that the proxy behavior would replace this “default” behavior, but it looks like from my testing that the proxy synchronization takes place, followed by the “base” behavior. This resulted in two entries being made in the Courses collection each time a Course was assigned to the Department. I removed the base behavior, which means that if the in-memory repository is used, the client code will need to synchronize the collection.







Next, we create the model. Right-click on the model canvas and select Generate Database from Model. This will create the DDL script to create the tables.



2010-09-12-1



Next, blank out the Custom Tool property on the file properties for the EDMX file. This way, no code will be generated for your model. This means we need to write our own ObjectContext class. Many authors recommend creating strongly-type properties for exposing each ObjectSet (Departments, Courses). You can do that, but it isn’t very useful for our Repository interface. Rather, we will create Query<T> and SetOf<T> methods to return the appropriately typed IQueryable and ObjectSet, respectively.





using System;
using System.Collections.Generic;
using System.Data.Objects;
using System.Linq;

namespace Model
{
public class PocoContext : ObjectContext
{
public PocoContext(string connectString)
:
base(connectString)
{
ContextOptions.LazyLoadingEnabled
= true;
}

Dictionary
<Type, ObjectQuery> roots = new Dictionary<Type, ObjectQuery>();

public ObjectSet<T> SetOf<T>() where T : class
{
ObjectQuery root;
if (!roots.TryGetValue(typeof(T), out root))
{
var
set = CreateObjectSet<T>();
roots[
typeof(T)] = set;
return set;
}

return (ObjectSet<T>)root;
}

public IQueryable<T> Query<T>() where T : class
{
return (IQueryable<T>)SetOf<T>();
}
}
}







Finally, we create our Repository implementation.



using System.Linq;

namespace Model.School.Model2
{
using Interfaces;

public class SchoolRespository : BaseRepository
{
private PocoContext context;

public SchoolRespository(string connectString = "name=Model2Container")
{
context
= new PocoContext(connectString);
}

public override IQueryable<T> Query<T>()
{
return context.Query<T>();
}

public override T New<T>()
{
return context.CreateObject<T>();
}

public override void SetNext<T>(T obj)
{
// no need for this with SQL Server auto-numbering
}

public override void Add<T>(T obj)
{
context.SetOf
<T>().AddObject(obj);
}

public override void Remove<T>(T obj)
{
context.SetOf
<T>().DeleteObject(obj);
}

public override void Commit()
{
context.SaveChanges();
}
}
}





Here is a test that shows how to use the SchoolRepository that we have created.



[TestMethod]
public void Test_SchoolRepository()
{
IRepository repo
= new SchoolRespository();

var count
= repo.Query<Department>().Count();

try
{
var math
= repo.CreateNext<Department>(d =>
{
d.Name
= "Mathematics";
});

var algebra
= repo.CreateNext<Course>(c =>
{
c.Name
= "Algebra";
c.Department
= math;
});

repo.Commit();

repo
= new SchoolRespository();
var course
= (from c in repo.Query<Course>()
where c.Name == "Algebra"
select c).First();
Assert.IsNotNull(course);
Assert.IsTrue(course.Department.Id
== math.Id);

var dept
= (from d in repo.Query<Department>()
where d.Name == "Mathematics"
select d).First();
Assert.IsTrue(dept.Courses.Count
== 1);
Assert.IsTrue(dept.Courses[
0] == course);

}
finally
{
repo
= new SchoolRespository();

// remove course and dept

var course
= repo.Query<Course>()
.Where(o
=> o.Name == "Algebra").FirstOrDefault();
if (course != null) repo.Remove<Course>(course);

var dept
= repo.Query<Department>()
.Where(o
=> o.Name == "Mathematics").FirstOrDefault();
if (dept != null) repo.Remove<Department>(dept);
repo.Commit();
}
}

Thursday, September 9, 2010

A Repository-like façade for mocking Entity Framework

While I know there are a lot of people in the ALT.NET community who like to mock Enitity Framework, that is not what I am talking about.

The objective of this exercise is to develop an Interface that can be used by Business Logic to query and persist data as well as provide and in-memory “mock” for testing or prototyping without a database.

The paradigm used is that of object model aggregates typically found in Domain-driven designs (DDD). This is fortunate because it is the model used by EF, where the aggregates are called ObjectSets.

We want to take advantage of LINQ, because this will allow the consumer of the Repository to add query operators prior to executing the query. The Repository will provide a Query method, a New method, an Add method, a Remove method and a Commit method.

I used the term “a repository-like facade” in the title of this post because traditionally a Repository provides access to a single Aggregate. I have decided to allow an EF Context, which might have several aggregates, to be wrapped by my Repository-implementation. The root aggregate type is determined by the Type parameter affixed to the method. In addition, I will provide a number of convenience methods to chain some of these basic methods is a single method call.

Here is the interface:

using System;
using System.Linq;

namespace Interfaces
{
public interface IRepository
{
// returns a query object for an aggregate root
IQueryable<T> Query<T>();

// returns a new object of the type requested
T New<T>() where T : class;

// returns a new object of the type requested (with the next id set)
T Next<T>() where T : class;

// adds the object to the aggregate root
void Add<T>(T obj) where T : class;

// gets a new object and Adds it to the collection
T AddNew<T>() where T : class;

// gets a new object (with next id set) and Adds it to the collection
T AddNext<T>() where T : class;

// adds a new object with the next id, runs initializer and persists it
T CreateNext<T>(Action<T> initializer) where T : class;

// remove an aggregate root
void Remove<T>(T obj) where T : class;

// persists any changes
void Commit();
}

}







The following code is an abstract implementation of the convenience methods, which are independent of the actual method of creating the new objects and managing them in the context. The methods that are declared abstract are the ones that will need to be implemented by a concrete Repository.



Note: The exception handling in these code listings has been omitted for brevity.





using System;
using System.Linq;

namespace Interfaces
{
abstract public class BaseRepository : IRepository
{
abstract public IQueryable<T> Query<T>();

abstract public T New<T>() where T : class;

abstract public void SetNext<T>(T obj) where T : class;

abstract public void Add<T>(T obj) where T : class;

abstract public void Remove<T>(T obj) where T : class;

abstract public void Commit();

public T Next<T>() where T : class
{
var obj
= New<T>();
SetNext
<T>(obj);
return obj;
}

public T AddNew<T>() where T : class
{
var obj
= New<T>();
Add
<T>(obj);
return obj;
}

public T AddNext<T>() where T : class
{
var obj
= Next<T>();
Add
<T>(obj);
return obj;
}

public T CreateNext<T>(Action<T> initializer) where T : class
{
var obj
= AddNext<T>();
if (initializer != null) initializer(obj);
Commit();
return obj;
}
}
}





We can implement an in-memory repository that maintains each type of aggregate root in an ArrayList and uses the Type to find the correct List and operate on it accordingly. To simulate auto-numbered primary keys, we assume that auto-numbered entities will have a long Id property and maintain a single counter for all entities. Of course, you are free to implement this any way that works for you. The Commit() method is a no-op since we don’t plan on persisting the data to disk, but you can implement a Repository that does this if you like.



This implementation works with concrete entity classes (POCOs). I originally had a version that worked with interfaces and the repository mapped the interfaces to an implementation. This worked well with Entity Framework and its generated EntityObject classes, but fell down when I tried to use it with WCF RIA Services.



using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;

namespace Interfaces
{
public class InMemRepository : BaseRepository
{
public InMemRepository()
{
// could data load from disk here
}

Dictionary
<Type, ArrayList> roots = new Dictionary<Type, ArrayList>();
long counter = DateTime.Now.Ticks;

private ArrayList GetRootList<T>()
{
ArrayList list;
if (!roots.TryGetValue(typeof(T), out list))
{
list
= new ArrayList();
roots[
typeof(T)] = list;
}
return list;
}

public override IQueryable<T> Query<T>()
{
var list
= GetRootList<T>();
return list.Cast<T>().AsQueryable<T>();
}

public override T New<T>()
{
return Activator.CreateInstance<T>();
}

// assumes that there is an Id property (long)
public override void SetNext<T>(T obj)
{
var idProperty
= typeof(T).GetProperty("Id");
idProperty.SetValue(obj, counter
++, null);
}

public override void Add<T>(T obj)
{
var list
= GetRootList<T>();
list.Add(obj);
}

public override void Remove<T>(T obj)
{
var list
= GetRootList<T>();
list.Remove(obj);
}

public override void Commit()
{
// code here to write to disk
}
}
}





Here is a unit test that demonstrates how to work with the repository:





[TestClass()]
public class InMemRepositoryTest
{
public class Department
{
public virtual long Id { get; set; }

public virtual string Name { get; set; }

private IList<Course> _courses = new List<Course>();
public virtual IList<Course> Courses { get { return _courses; } }
}

public class Course
{
public virtual long Id { get; set; }

public virtual string Name { get; set; }

private Department _department;
public virtual Department Department { get { return _department; }
set
{
if (_department != null) _department.Courses.Remove(this);
_department
= value;
if (_department != null) _department.Courses.Add(this);
}
}
}

[TestMethod]
public void Test_InMemRepository()
{
IRepository repo
= new InMemRepository();

// create some departments
var math = repo.AddNext<Department>();
Assert.IsNotNull(math);
Assert.IsInstanceOfType(math,
typeof(Department));
Assert.IsTrue(math.Id
> 0);

math.Name
= "Mathematics";
repo.Commit();

// use the convenience method
var compsci = repo.CreateNext<Department>(d =>
{
d.Name
= "Computer Science";
});
Assert.IsNotNull(compsci);
Assert.IsInstanceOfType(compsci,
typeof(Department));
Assert.IsTrue(compsci.Id
> 0);
Assert.IsTrue(compsci.Name
== "Computer Science");

var count
= repo.Query<Department>().Count();
Assert.AreEqual
<int>(count, 2);

// create some courses
var algebra = repo.CreateNext<Course>(c =>
{
c.Name
= "Algebra";
c.Department
= math;
});

var trig
= repo.CreateNext<Course>(c =>
{
c.Name
= "Trigonometry";
c.Department
= math;
});

var lisp
= repo.CreateNext<Course>(c =>
{
c.Name
= "Lisp";
c.Department
= math;
});

Assert.AreEqual
<int>(3, repo.Query<Course>().Count());
Assert.AreEqual
<int>(3, math.Courses.Count());
Assert.AreEqual
<int>(0, compsci.Courses.Count());

lisp.Department
= compsci;
Assert.AreEqual
<int>(2, math.Courses.Count());
Assert.AreEqual
<int>(1, compsci.Courses.Count());
}
}







My next post will show how to write a Repository implementation for Entity Framework.

Thursday, May 7, 2009

Authorization Strategies for the Business Layer

It's tempting to design a Business Layer that accepts User identity information and attempts to authenticate and authorize the user. However, security is a cross-cutting concern, and as such, should not be intertwined with your business logic.

kick it on DotNetKicks.com

The strategies presented here will extract the authorization component from the business logic and embed it as a separate concern within the Business Layer. I'm going to ignore the authentication function, and focus on determining what authority an authenticated user has to call functions in the Business Layer.

Two-step Business Layer Factory

try
{
using(IFactory factory = AuthenticatedFactory.New(user, pw))
{
IOrderProcessing processing = factory.CreateOrderProcessing();
return processing;
// or
// container.RegisterInstance<IOrderProcessing>(processing);
}
}
catch (AuthenticationError e) { }
catch (AuthorizationError e) { }
finally
{
// clean up
}



The authentication is done in the AuthenticationFactory. If the AuthenticationFactory has dependencies on a data layer or LDAP provider, you can trade in the static New method approach for a dependency injection approach:



public class AuthenticatedFactory 
{
public AuthenticatedFactory(IDataLayer dataLayer)
{
DataLayer = dataLayer;
}
// more code
}



Get your factory this way:



using (IFactory factory = container.Resolve<AuthenticatedFactory>())
{
factory.User = user;
factory.Password = pw;
// get the business layer
}



Fine-grained Authorization using Sub-classes



One strategy for the Business Layer is to have coarse-grained authorization to the BusinessLayer. The user is either allowed to access that particular Business Layer, or an AuthorizationError is thrown. To make the access more fine-grained, the IOrderProcessing class that is returned can be tailored to the privileges that the authenticated user has. In either case, the factory method CreateOrderProcessing with determine the access level for the user.



For example suppose the IOrderProcessing interface offers three methods: LookupOrder(), EnterOrder() and ApproveOrder(). There are three levels of access: managers can access all three, clerks can access the first two, and salespeople can only access LookupOrder(). This can be accommodated by four classes and the factory determines which to return to the application.



public class NoAccessOrderProcessing : IOrderProcessing
{
public virtual Order LookupOrder() { throw new AuthenticationError(); }
public virtual void EnterOrder(Order o) { throw new AuthenticationError(); }
public virtual void ApproveOrder(Order o) { throw new AuthenticationError(); }
}

public class SalespersonOrderProcessing : NoAccessOrderProcess
{
public override Order LookupOrder() { /* code here */ }
}

public class ClerkOrderProcessing : SalespersonOrderProcessing
{
public override void EnterOrder(Order o) { /* code here */ }
}

public class ManagerOrderProcessing : ClerkOrderProcessing
{
public override void ApproveOrder(Order o) { /* code here */ }
}



This approach has the advantage of removing the authorization logic from the business logic, but it embeds the authorization logic in your class hierarchy. The designer of the business logic will need to be aware of the authorization model at design-time. However, if you know that the functions permitted to each role are going to be static, this approach has merit.



Single business class with Static-bound delegates



An alternate approach uses indirection through delegates. This strategy will move the logic entirely out of the class hierarchy and into the Factory class. The public methods on the business layer will call delegates that are, by default, set to the methods that perform the actual business logic. The Factory can disable certain methods by setting the delegates to null prior to handing the business layer object to the application.




public delegate Order LookupHandlerType();
public delegate void ProcessOrderType(Order o);

public class OrderProcessing : IOrderProcessing
{
public LookupHandlerType LookupHandler;
public ProcessOrderType EnterHandler;
public ProcessOrderType ApproveHandler;

public OrderProcessing(IDataLayer dataLayer) {
DataLayer = dataLayer;

LookupHandler = _LookupOrder;
EnterHandler = _EnterOrder;
ApproveHandler = _ApproveOrder;

}

private IDataLayer DataLayer { get; set; }

public Order LookupOrder() {
if (LookupHandler == null)
throw new AuthorizationError();
return LookupHandler();
}

public void EnterOrder(Order o) {
if (EnterHandler == null)
throw new AuthorizationError();
EnterHandler(o);
}

public void ApproveOrder(Order o) {
if (ApproveHandler == null)
throw new AuthorizationError();
ApproveOrder(o);
}

// business logic in these methods
private Order _LookupOrder() { return new Order(); }
private void _EnterOrder(Order o) { }
private void _ApproveOrder(Order o) { }

}

public class Factory
{
public IOrderProcessing CreateOrderProcessing()
{
// set these based on role user is in.
bool manager = false;
bool clerk = true;
bool salesperson = true;

//var processing = container.Resolve<IOrderProcessing>() as OrderProcessing;
OrderProcessing processing = new OrderProcessing(new MyDataLayer());



if (!manager) processing.ApproveHandler = null;
if (!clerk) processing.EnterHandler = null;
if (!salesperson) processing.LookupHandler = null;
return processing;
}
}



Dynamic-binding Authorization



As a further refinement, rather than statically binding to the Handler delegate properties, we could have the names of the Handlers stored in a database or file and use Reflection to set them to null if the role disallows access.



    public class DynamicFactory
{
public IOrderProcessing CreateOrderProcessing()
{

//var processing = container.Resolve<IOrderProcessing>() as OrderProcessing;
OrderProcessing processing = new OrderProcessing(new MyDataLayer());

//get user role, list of prohibited methods from authorization database
//
var prohibitedHandlers = new List<string>()
// { "ApproveHandler", "EnterHandler" };
//disable access
foreach (string handler in prohibitedHandlers)
{
var field = processing.GetType().GetField(handler);
field.SetValue(processing, null);
}
return processing;
}
}

I've presented some strategies for authorizing access to your business layer objects. It's important to keep authorization code separated from your business logic, since it is a cross-cutting concern and since security models will likely change over time, it makes sense to encapsulate the access in a Factory type object that can evolve over time. The key is that the business logic object that is handed to the application is already configured for the privileges that the user has and the authorization checking does not need to be embedded in the business logic.


kick it on DotNetKicks.com

Monday, May 4, 2009

WPF Model-View-ViewModel Toolkit

The WPF team at Microsoft has released a toolkit (version 0.1) that addresses developing UIs with the M-V-VM pattern.

It's definitely a first-pass (e.g. no VB.NET support), but they are looking for feedback on this effort. There is also a bit of confusion as to how this compares to the Silverlight development pattern in RIA Services. See this StackOverflow discussion.

The toolkit includes:

  • A Visual Studio 2008 template (Visual C# Express 2008 also supported)
  • Documentation
    • General introduction to M-V-VM
    • Walkthrough using the VS template
  • A complete WPF application demonstrating the M-V-VM pattern

Here's a post about ViewModel and how it enhances the UI's testability.

Check it out here: WPF Model-View-ViewModel Toolkit


kick it on DotNetKicks.com

Saturday, April 11, 2009

Book Recommendation: Framework Design Guidelines (2nd ed.)

The authoritative work by Brad Abrams and Krzysztof Cwalina on .NET framework design was recently updated.

The Book: Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries (2nd Edition)

The Blog: http://blogs.msdn.com/brada/archive/tags/Framework+Design+Guidelines/default.aspx

The Blurb:

Framework Design Guidelines, Second Edition, teaches developers the best practices for designing reusable libraries for the Microsoft .NET Framework. Expanded and updated for .NET 3.5, this new edition focuses on the design issues that directly affect the programmability of a class library, specifically its publicly accessible APIs.

This book can improve the work of any .NET developer producing code that other developers will use. It includes copious annotations to the guidelines by thirty-five prominent architects and practitioners of the .NET Framework, providing a lively discussion of the reasons for the guidelines as well as examples of when to break those guidelines.

Microsoft architects Krzysztof Cwalina and Brad Abrams teach framework design from the top down. From their significant combined experience and deep insight, you will learn

  • The general philosophy and fundamental principles of framework design
  • Naming guidelines for the various parts of a framework
  • Guidelines for the design and extending of types and members of types
  • Issues affecting–and guidelines for ensuring–extensibility
  • How (and how not) to design exceptions
  • Guidelines for–and examples of–common framework design patterns

 

Friday, October 3, 2008

The Common Service Locator

I have argued against making 'hard' references to an underlying Dependency Injection (or IoC) container; rather, allow the container to do the work for you, namely, inject the dependencies. I realize that it can be difficult in practice, and apparently so have others.

A group of DI container authors have come together to define a common interface for using the underlying containers without creating a hard reference to a particular implementation. This is useful when you are writing code that needs to use a container to resolve a dependency (i.e. get an instance) but you don't know or care what container is being used.

So now we have the Common Service Locator library. Thanks to Ayende for blogging it. UPDATE: Also Glenn Block.

Each container needs an adapter to implement the interface and do the translation from the common method calls to the native container calls. This allows all container references to be declared as Microsoft.Practices.ServiceLocation.IServiceLocator.

Your code has two ways of getting the container:

  • The IServiceLocater reference can be supplied by the calling code and you just use it, or
  • You code can use a static property, ServiceLocator.Current.

Here is the interface that you will use (API Reference):

using System;
using System.Collections.Generic;

namespace Microsoft.Practices.ServiceLocation
{
// Summary:
// The generic Service Locator interface. This interface is used to retrieve
// services (instances identified by type and optional name) from a container.
public interface IServiceLocator : IServiceProvider
{
// Summary:
// Get all instances of the given TService currently registered in the container.
//
// Type parameters:
// TService:
// Type of object requested.
//
// Returns:
// A sequence of instances of the requested TService.
//
// Exceptions:
// Microsoft.Practices.ServiceLocation.ActivationException:
// if there is are errors resolving the service instance.
IEnumerable<TService> GetAllInstances<TService>();
//
// Summary:
// Get all instances of the given serviceType currently registered in the container.
//
// Parameters:
// serviceType:
// Type of object requested.
//
// Returns:
// A sequence of instances of the requested serviceType.
//
// Exceptions:
// Microsoft.Practices.ServiceLocation.ActivationException:
// if there is are errors resolving the service instance.
IEnumerable<object> GetAllInstances(Type serviceType);
//
// Summary:
// Get an instance of the given TService.
//
// Type parameters:
// TService:
// Type of object requested.
//
// Returns:
// The requested service instance.
//
// Exceptions:
// Microsoft.Practices.ServiceLocation.ActivationException:
// if there is are errors resolving the service instance.
TService GetInstance<TService>();
//
// Summary:
// Get an instance of the given named TService.
//
// Parameters:
// key:
// Name the object was registered with.
//
// Type parameters:
// TService:
// Type of object requested.
//
// Returns:
// The requested service instance.
//
// Exceptions:
// Microsoft.Practices.ServiceLocation.ActivationException:
// if there is are errors resolving the service instance.
TService GetInstance<TService>(string key);
//
// Summary:
// Get an instance of the given serviceType.
//
// Parameters:
// serviceType:
// Type of object requested.
//
// Returns:
// The requested service instance.
//
// Exceptions:
// Microsoft.Practices.ServiceLocation.ActivationException:
// if there is an error resolving the service instance.
object GetInstance(Type serviceType);
//
// Summary:
// Get an instance of the given named serviceType.
//
// Parameters:
// serviceType:
// Type of object requested.
//
// key:
// Name the object was registered with.
//
// Returns:
// The requested service instance.
//
// Exceptions:
// Microsoft.Practices.ServiceLocation.ActivationException:
// if there is an error resolving the service instance.
object GetInstance(Type serviceType, string key);
}
}



Here are the containers that have adapters at the moment:





I recommend IServiceLocator be used in all components that might need a reference to a container. Note that they are no common calls for configuring the container because this is a container-specific task that should be handled in the calling code.

Saturday, July 12, 2008

Ninject revisited

In a previous post, I looked at Ninject, and based on a cursory look at the documentation, dismissed it as requiring me to decorate my component classes with attributes in order to use multi-parameter constructor injection. Thanks to a comment by ninject's author, Nate Kohari, I found that with a slight configuration change, we can duplicate the behavior of Unity.

The proof's in the pudding. Let's see if we can wire up the same components with both Unity and Ninject without having to make any changes to our component classes.

Here are some interfaces:

public interface IDataService
{
}

public interface ISecurityService
{
}

public interface ILogger
{
}


And here are some components that use them. The Business Logic requires all three, the Security service needs a DataService and Logger, and the DataService needs a Logger.



public class BusinessLogic
{
protected IDataService DataService { set; get; }
protected ILogger Logger { set; get; }
protected ISecurityService SecurityService { set; get; }

public BusinessLogic()
{
}

public BusinessLogic(ILogger logger, IDataService dataService, ISecurityService securityService)
:this()
{
this.Logger = logger;
this.DataService = dataService;
this.SecurityService = securityService;
}


public override string ToString()
{
return base.ToString() + '\n' +
Logger.ToString() + '\n' +
DataService.ToString() + '\n' +
SecurityService.ToString() + '\n'
;
}
}


public class DataService : IDataService
{
protected ILogger Logger { set; get; }

public DataService()
{
}

public DataService(ILogger logger)
:this()
{
this.Logger = logger;
}
}

public class SecurityService : ISecurityService
{

protected IDataService DataService { set; get; }
protected ILogger Logger { set; get; }

public SecurityService()
{
}

public SecurityService(ILogger logger, IDataService dataService)
: this()
{
this.Logger = logger;
this.DataService = dataService;
}
}

public class Logger : ILogger
{
}


If we don't want to use an auto-wring container, we need to know all the dependecies and create the Business object like so:



static BusinessLogic NormalWay()
{
var logger = new Logger();
var dataService = new DataService(logger);
var securityService = new SecurityService(logger, dataService);
var bizLogic = new BusinessLogic(logger, dataService, securityService);
return bizLogic;
}



How do we configure and create a BusinessLogic object with Unity? Like so:



static BusinessLogic UnityWay(UnityContainer container)
{
UnityContainer container = new UnityContainer();
container
.RegisterType<ILogger, Logger>()
.RegisterType<IDataService, DataService>()
.RegisterType<ISecurityService, SecurityService>()
;
var bizLogic = container.Resolve<BusinessLogic>();
return bizLogic;
}
}


Likewise, we can create a method to create a BusinessLogic object using Ninject, all auto-wired are ready to go. This however, requires a configuration class (MyModule):



static BusinessLogic NinjectWay()
{
var kernel = new StandardKernel(new MyModule(), new AutoWiringModule());
var bizLogic = kernel.Get<BusinessLogic>();
return bizLogic;

}
private class MyModule : StandardModule
{
public override void Load()
{
Bind<ILogger>().To<Logger>();
Bind<IDataService>().To<DataService>();
Bind<ISecurityService>().To<SecurityService>();
}
}



We can run the following to show that the objects get create and populate the services:



static void Main(string[] args)
{
BusinessLogic bz;

bz = NormalWay();
System.Console.WriteLine(bz);

bz = UnityWay();
System.Console.WriteLine(bz);

bz = NinjectWay();
System.Console.WriteLine(bz);

}

So the end result is that we can design our components and use constructor-injection. So long as we keep container-dependencies out of our business components, an app can be assembled using the container of your choice.