Click here to Skip to main content
Click here to Skip to main content

Swapping Out Concrete Implementations of Interfaces with IoC/DI using Castle Windsor

, 15 Jan 2014
Rate this:
Please Sign up or sign in to vote.
How to swap out interface mappings in IoC/DI projects using Castle Windsor

IoC/DI Has Little Point If You Don't Swap your Maps

This tip is sort of an add-on to the article here

The whole point of Inversion of Control is so that you can pass different concrete implementations of an interface to a Controller that expects a class that implements a specific interface, but does not specify or even care what precise class it receives.

To specify which implementing class is used, you might write code such as this:

    public class RepositoriesInstaller : IWindsorInstaller
    {
        public void Install(IWindsorContainer container, IConfigurationStore store)
        {
            container.Register(
                Component.For<iduckbilledplatypusrepository>().ImplementedBy
                <duckbilledplatypusrepository>().LifestylePerWebRequest(),
                Component.For<isiberiantigerrepository>().ImplementedBy
                <siberiantigerrepository>().LifestylePerWebRequest(),
                Component.For<ibottlenoseddolphinrepository>().ImplementedBy
                <bottlenoseddolphinrepository>().LifestylePerWebRequest(),
                Component.For<ipterodactylrepository>().ImplementedBy
                <pterodactylrepository>().LifestylePerWebRequest(),
                Component.For<ibutterflyrepository>().ImplementedBy
                <butterflyrepository>().LifestylePerWebRequest());
        }
    }

But wait a minute -- "Whoa there, pard!" you might be saying. Isn't that a bit verbose? It's true there are other ways -- three, in fact - that you can map your interfaces (that is to say, the interfaces that are represented as argument types in your Controller's constructors): You can use XML files (which have the advantage of late binding), you can use auto-wiring or auto-registering, allowing the compiler to use reflection and register all interfaces you tell it to find, or you can do it in code, as shown above. The first way (XML) is largely considered passé today because of certain similarities with Peanut Brittle; the middle (auto-wiring) is definitely the hottest on the coolness scale (or the coolest on the...never mind); but I prefer the latter way, as shown above, for its easy readability. And, because it's easy to read, it's easy to maintain (if at times admittedly tedious) and to add grokkable logic to it.

As to the three ways of mapping your concrete classes to your interfaces, here is a (IMHO/YMMV) chart of their qualities/maladies:

Grokkability PIA Factor* FancyPantsiness
XML 10 8 2
Code 10 5 4
Auto-Wiring 2 2 10

*Note: PIA == "Pain In the Ankle"

Enough with the scientific charts, already!

So, let's get back down to business. As to using the "Code" method: For instance (no pun intended), if you want to swap out one set of implementers with another based on some condition, it is easy to add that sort of logic:

    const int HAPPINESS = 42;
    int Money;
    int Love;
    . . .
    public class RepositoriesInstaller : IWindsorInstaller
    {
        public void Install(IWindsorContainer container, IConfigurationStore store)
        {
	if (Love == HAPPINESS)
	{	
	            container.Register(
               		Component.For>imammalrepository>().ImplementedBy>
               		duckbilledplatypusrepository>().LifestylePerWebRequest(),
                		Component.For>ifishrepository>().ImplementedBy>
                		bottlenoseddolphinrepository>().LifestylePerWebRequest(),
                		Component.For>ibirdrepository>().ImplementedBy>
                		pterodactylrepository>().LifestylePerWebRequest(),
                		Component.For>ireptilerepository>().ImplementedBy>
                		hornedtoadrepository>().LifestylePerWebRequest());
                		Component.For>iinsectrepository>().ImplementedBy>
                		beetlerepository>().LifestylePerWebRequest());
	}
	else if (Money == HAPPINESS)
	{	
	            container.Register(
               		Component.For>imammalrepository>().ImplementedBy>
               		siberiantigerrepository>().LifestylePerWebRequest(),
                		Component.For>ifishrepository>().ImplementedBy>
                		catfishrepository>().LifestylePerWebRequest(),
                		Component.For>ibirdrepository>().ImplementedBy>
                		africangreyparrotrepository>().LifestylePerWebRequest(),
                		Component.For>ireptilerepository>().ImplementedBy>
                		bullfrogrepository>().LifestylePerWebRequest());
                		Component.For>iinsectrepository>().ImplementedBy>
                		prayingmantisrepository>().LifestylePerWebRequest());
	}
	else 
	{
		... // deal with it
	}
        }
    }

Of course, your conditional logic will differ (hopefully); and, for this to work, you will need to have created multiple (two, in this case) classes that implement each of the interfaces.

If different users should get different implementers, or if you want to use certain classes while debugging/testing and others for "production" code, this sort of scenario may come in handy for you.

That's all he wrote!

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

B. Clay Shannon
Publisher "Found in the Translation"
United States United States
I am the entire team at "Found in the Translation," which produces multilingual books (paperback and Kindle versions) such as "Don Quixote: In Spanish and English, Paragraph-by-Paragraph" among many others (English paired with not only Spanish, but also French and even Finnish). You can see all those books here: http://jsfiddle.net/clayshannon/pRgQL/75/
 
Personal web sites that I have created can be seen at http://usamaporama.azurewebsites.net and http://bigsurgarrapata.azurewebsites.net/ and http://www.awardwinnersonly.com
 
Peripatetic and picaresque, I have lived in eight states; specifically, besides my native California (where I was born and where I now again reside) in chronological order: New York, Montana, Alaska, Oklahoma, Wisconsin, Idaho, and Missouri.
 
I am also a writer of both fiction (for which I use a nom de plume, "Blackbird Crow Raven", as a nod to my Native American heritage - I am "half cowboy, half Indian") and nonfiction: http://www.lulu.com/spotlight/blackbirdcraven
Follow on   Twitter   Google+   LinkedIn

Comments and Discussions

 
-- There are no messages in this forum --
| Advertise | Privacy | Mobile
Web04 | 2.8.140721.1 | Last Updated 15 Jan 2014
Article Copyright 2014 by B. Clay Shannon
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid