Content by Category
.NET 1.x
.NET 2.0
.NET 3.0
.NET 3.5
.NET 4.0
.NET Assemblies
.NET Framework
.NET Getting Started
Accessibility
ADO.NET
Advertorials
Agile Development
AJAX
Architecture
ASP.NET
ASP.NET MVC
ASP.NET WebForms
B2B (Business Integration)
BizTalk
Book Excerpts
Build and Deploy
C#
C++
Code Contracts
CODE on the Road!
COM+
Community
Conferences
Continuous Integration
Crystal Reports
CSLA.NET
CSS
Data
Design Patterns
Development Process
Display Technologies
Distributed Computing
DotNetNuke
DSL
Dynamic Programming
Editorials
Enterprise Services ("COM+")
Entity Framework
Events
Expression Blend
F#
Fox to Fox
Frameworks
Functional Programming
Graphics
Internet Explorer 8.0
Interviews
iPhone
Java
Java Script
jQuery
LINQ
Linux
Mac OS X
MDX
Microsoft Application Blocks
Microsoft Business Rules Framework
Microsoft Expression
Microsoft Office
Mobile Development
Mobile PC
Mono
Network
NHibernate
Object Oriented Development
Open Source
Opinion
Opinions
Oracle
ORM
Other Languages
Parallel Programming
Patterns
Podcasts
Post Mortem
PowerPoint
Print/Output
Product News
Product Reviews
Project Management
Python
Q&A
Reporting Services
REST
RIA Services
Ruby
Search
Security
Services
SharePoint
Silverlight
SOA
Social Networks
Software & Law
Software Business
Source Control
Speech-Enabled Applications
SQL Server
SQL Server 2000
SQL Server 2005
SQL Server 2008
SQL Server CE/AnyWhere/Mobile/Compact
Subversion
Sync Framework
Tablet PC
TDD
Team System
Techniques
Testing and Quality Control
Tips
UI Design
UML
User Groups
VB Script
VB.NET
VFP and .NET
VFP and SQL Server
Virtual Earth
Vista
Visual Basic
Visual Basic 6 (and older)
Visual FoxPro
Visual Studio .NET
Visual Studio 2005
Visual Studio 2008
Visual Studio 2010
Visual Studio Tools for Office
VSX
WCF
Web Development (general)
Web Services
WF
Whitepapers
Windows 7
Windows Azure
Windows Live
Windows Server
Windows Vista
WinForms
Workflow
WPF
XAML
XML
XNA
XSLT



ESDC


 


State of .NET


Reader rating:
Click here to read 2 comments about this article.
Article source: CoDe (2009 May/Jun)


Article Pages:  1  2 3 - Next >


Bricks and Mortar: Building a Castle

In an application built with object-oriented techniques, objects are the bricks. You construct little pieces of code encapsulated in these bricks. To build bigger structures, you need to hold these bricks together. You can hardwire them together by instantiating dependent objects within your objects, but it makes the whole structure less flexible in the face of change. So you can adopt an inversion of control (IoC) container to act as your mason to assemble your bricks into complex structures that can flex with changing requirements. In this article, I will examine a popular IoC container, Castle Windsor, and how it enables you to build flexible and robust applications. If you are new to IoC containers and dependency injection, I would recommend reading Martin Fowler's article, Inversion of Control Containers and the Dependency Injection Pattern (http://martinfowler.com/articles/injection.html) and my own article from the March 2008 edition of MSDN Magazine, Loosen Up: Tame Your Dependencies for More Flexible Apps (http://msdn.microsoft.com/en-us/magazine/cc337885.aspx).

IoC Containers perform two basic functions: putting dependencies in and getting fully constructed objects out. I will start by examining how to get fully constructed objects out of your container, and then move on to the more complex aspect of proper configuration of dependencies between objects that you place in the container.

Masonry 101

The first job of a container is to respond to your requests for fully constructed objects by resolving their dependencies and cementing them together for you:

var ap = IoC.Resolve<IAccountsPayable>();

When you ask for an implementation of IAccountsPayable, it is the job of the container to determine which class implements IAccountsPayable, determine the dependencies of this class and any sub-dependencies, and then create instances of all dependencies, building them up as it goes along. You will notice that rather than tying yourself to any particular IoC container, the static gateway pattern is used to decouple the code from a concrete implementation. Let's look at the implementation of IoC. Although IoC is a static class, it forwards all requests to an inner resolver, which is an adapter for the real IoC container:

public static class IoC {
 private static IDependencyResolver resolver;
 public static void Initialize(
                   IDependencyResolver resolver) {
   this.resolver = resolver;
 }
 public static T Resolve<T>(){...}
 public static T Resolve<T>(string key){...}
 public static T Resolve<T>(object anonType){...}
 public static T Resolve<T>(string key,
                            object anonType){...}
 public static IEnumerable<T> ResolveAll<T>(){...}
}

At application startup, you bootstrap your chosen IoC (in this case Castle Windsor) using:

var container = new WindsorContainer();
var resolver = new WindsorDependencyResolver(container);
IoC.Initialize(resolver);

Notice that IoC and IDependencyResolver do not have any container configuration methods. All the methods (except Initialize()) are devoted to resolving fully constructed objects. You can get dependencies out, but you cannot get dependencies in. This is because containers vary widely on how dependencies are configured in the container. It is the job of the bootstrapper to get the container ready to resolve dependencies in a container-specific way before calling IoC.Initialize().

Let's look at the various ways to get objects out of the container...

Hey, Container, I Need an IAccountsPayable

The most common container lookup is asking the container for the implementer of a particular interface:

var ap = IoC.Resolve<IAccountsPayable>();

You ask the container for the implementer of IAccountsPayable and it returns an object that implements the requested interface. The returned object is ready to perform work for you when you call its methods/properties. Any of AccountsPayable's dependencies have been resolved and satisfied before it is returned to you.

If multiple implementations of IAccountsPayable have been registered in the container, Castle Windsor returns the first one registered. (Note: This is an area where containers differ substantially. Some containers throw an exception if multiple implementations have been registered whereas others return the last implementation registered. Read the container documentation carefully if you are contemplating switching from one IoC container to another and are dependent on this override behavior.)

In the Key of T

Let's say you are integrating multiple databases and access them via IDbGateway implementations. You have an IDbGateway per database registered in the IoC container. How do you get the specific IDbGateway that you are looking for? If you need a specific implementation, you can request it by string-based key:

var gateway = 
IoC.Resolve<IDbGateway>(DatabaseKey.Reporting);

where DatabaseKey.Reporting is simply a string constant, "reporting". You can now use this specific implementation to access the Reporting database via the IDbGateway object.

Getting Greedy

What if you need all implementations of a particular interface? I want all registered validators for invoices:

var validators = 
IoC.Resolve<IValidator<Invoice>>();

Notice that Castle Windsor can resolve generic interfaces and implementations. You get back all types that are registered as implementing IValidator<Invoice>, but not implementers of IValidator<Customer>. This allows you to write very general code that can validate invoices without tying yourself to a particular set of validation rules. Some of these validation rules may actually be added at run time after the application is deployed!

I Have Something You Might Need

Sometimes you need to supply an externally created instance as a constructor argument. For example, the ASP.NET pipeline creates derived instances of Page. Another example would be WPF creating instances of XAML Pages/Windows. These are your views, which are a dependency of your Presenters/ViewModels. Windsor allows you to supply externally created dependencies as constructor arguments. For example, in the ASPX page's constructor, you would call:

presenter = PresenterFactory.Create
              <AccountsPayablePresenter>(this);

Notice that you are passing "this" as the view to the PresenterFactory because you want to wire the Presenter to the view instance (ASPX page) created by the ASP.NET pipeline:

public class PresenterFactory {
    public static T Create<T>(IView someView) {
        return IoC.Resolve<T>(
                    new { view = someView });
    }
}

You construct an anonymous type with a property named "view", which matches the name of the constructor argument that you want to supply. You could have also used an IDictionary where the key is the name of the constructor argument. When satisfying dependencies, Windsor will use any registered dependencies as well as any supplied during the call to Resolve<T>() in order to construct an instance of the desired type.

Note: Whether you use anonymous types or keys in an IDictionary to supply externally created constructor arguments, it is your responsibility to ensure that the properties/keys match the names of the constructor arguments. If the constructor arguments are renamed, the corresponding anonymous type property/IDictionary key will not be renamed. Tests for the PresenterFactory (and similar classes) can verify that names match properly.

Getting Dependencies In

You know how to get fully constructed objects out, but how do you get all the dependencies into an IoC container so the container can do its job of constructing objects? Let's look at AccountsPayable. AccountsPayable needs to collaborate with some other objects to get its job done, namely an authorization service, an invoice validator, and an invoice repository. You define your list of dependencies using the AccountsPayable constructor:

public AccountsPayable(
         IAuthorizationService authService,
         IValidator<Invoice> invoiceValidator,
         IInvoiceRepository invoiceRepository) {
    this.authorizationService = authService;
    this.invoiceValidator = invoiceValidator;
    this.invoiceRepository = invoiceRepository;
}

This is known as constructor injection. The IoC container will create an instance of AccountsPayable using the above constructor supplying it with instances of the appropriate dependent objects.

Note that if any of AccountsPayable's dependencies had dependencies themselves, the IoC container would find and supply those as well. When wiring dependencies, the container walks the entire dependency graph and creates the dependencies in order from least dependent to most dependent. If a dependency cycle is found (A depends on B depends on A), Castle Windsor will throw an exception.

&

By: James Kovacs

James Kovacs is an independent architect, developer, trainer, and jack-of-all-trades, specializing in Agile development using the .NET Framework. He is passionate about helping developers create flexible software using test-driven development (TDD), unit testing, object-relational mapping, dependency injection, refactoring, continuous integration, and related techniques. James is a proud member of CodeBetter.com, a Microsoft Most Valuable Professional (MVP)-Solutions Architect, and card-carrying member of ALT.NET, a group of software professionals continually looking for more effective ways to develop applications. He received his Masters degree from Harvard University.

jkovacs@post.harvard.edu

Fast Facts

The concepts in the article are applicable to IoC containers in general, but the code examples will focus on Castle Windsor 2.0 RTM, which is available from The Castle Project (http://www.castleproject.org). Castle Windsor 2.0 RTM has not been officially released at the time of writing, but you can download the latest stable build from the Castle Project Build Server (http://builds.castleproject.org/) or retrieve and build latest source code from the Castle Project Subversion Repository (http://castleproject.org/subversion.html). Note that many of the features discussed are not available in Castle 1.0 RC3. So make sure you get Castle Windsor 2.0 RTM.



Article Pages:  1  2 3 - Next Page: 'The Road to Heck Is Paved in Angle Brackets' >>

Page 1: Bricks and Mortar: Building a Castle
Page 2: The Road to Heck Is Paved in Angle Brackets
Page 3: All Together Now

How would you rate the quality of this article?
1 2 3 4 5
Poor      Outstanding

Tell us why you rated the content this way. (optional)

Average rating:
3.5 out of 5

2 people have rated this article.

      CODE TRAINING

 

CODE TRAINING