Click here to Skip to main content
15,885,980 members
Articles / Web Development / ASP.NET
Tip/Trick

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

Rate me:
Please Sign up or sign in to vote.
5.00/5 (1 vote)
15 Jan 2014CPOL2 min read 10.5K   3  
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:

C#
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:

GrokkabilityPIA Factor*FancyPantsiness
XML1082
Code1054
Auto-Wiring2210

*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:

C#
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)


Written By
Founder Across Time & Space
United States United States
I am in the process of morphing from a software developer into a portrayer of Mark Twain. My monologue (or one-man play, entitled "The Adventures of Mark Twain: As Told By Himself" and set in 1896) features Twain giving an overview of his life up till then. The performance includes the relating of interesting experiences and humorous anecdotes from Twain's boyhood and youth, his time as a riverboat pilot, his wild and woolly adventures in the Territory of Nevada and California, and experiences as a writer and world traveler, including recollections of meetings with many of the famous and powerful of the 19th century - royalty, business magnates, fellow authors, as well as intimate glimpses into his home life (his parents, siblings, wife, and children).

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 "½ Cowboy, ½ Indian") and nonfiction, including a two-volume social and cultural history of the U.S. which covers important events from 1620-2006: http://www.lulu.com/spotlight/blackbirdcraven

Comments and Discussions

 
-- There are no messages in this forum --