Monthly Archives: August 2008

The Bitter Coder Tutorials, Binsor Style: Part IX, Constructor Injection

Previous posts in the series:

Part 9 of the original series focuses in on Constructor Injection, which is one method of doing Dependency Injection (the other is Setter Injection, which we’ll get to)   The reason to use Constructor or Setter Injection is a bit subjective, but (to me) boils down to if you the paramters to be mandatory and how many parameters you have.  We’re not here to debate, though, we’re here to copy Alex’s hard work….

Here’s the interface Alex defines;

public interface IEncoder

{

string Encode(string source);

}

And the two encoders:

public class NullEncoder:IEncoder

{

public string Encode(string source)

{

return source;

}

}

public class SillyEncoder:IEncoder

{

private char[] _mixedUp = “YACBDFEGIHJLKMONPRSQTUWVXZ”.ToCharArray();

public string Encode(string source)

{

string upperSource = source.ToUpper();

char[] encoded = new char[source.Length];

for (int i = 0; i < encoded.Length; i++)

{

encoded[i] = MapCharacter(upperSource[i]);

}

return new string(encoded);

}

private char MapCharacter(char ch)

{

if ((ch >= ‘A’) && (ch <= ‘Z’))

{

return _mixedUp[ch – ‘A’];

}

return ch;

}

}

Let’s check out the binsor:

component “null.encoder”, IEncoder, NullEncoder

component “silly.encoder”, IEncoder, SillyEncoder

component “message.sender”, SecretMessageSender:

_from=”ruprict@wordpress.com”

Notice we didn’t specify a value for the “_encoder” parameter, so Windsor will just plug in the first one it finds.  And, finally, the Program:

private static void Main(string[] args)

{

var sender = container.Resolve<SecretMessageSender>();

sender.SendMessage(“hammett”,“Howzit going at Microsoft?”);

}

Running this as is, gives us:

to: hammett
from: ruprict@wordpress.com

GOWZIQ EOIME YQ KICROSOFQ?

So, what if we want to send an unencrypted message?  Well, we can specify which IEncoder component to wire to our sender, like so:

component “message.sender”, SecretMessageSender:

_from=”ruprict@wordpress.com”

_encoder=@null.encoder

See?  We refer to it by the name we gave the component.  Running it now, gives us:

to: hammett
from: ruprict@wordpress.com

Howzit going at Microsoft?

(I bet he’s doing great…)

Setter injection…coming up!


The Bitter Coder Tutorials VIII: Referencing Instances By Key

Previous posts in the series:

In tutorial #8, Alex continues down his path of switching implementations around, but this time we are going to have multiple components that implement the same contract, and we’ll specify which one we want by id.  The id we are talking about is the id we gave the component when we registered it with Windsor.  Enough blah, blah, onto the code.

Here’s our class to read a file:

public class FileReader

{

public string FileName { get; set; }

public string ReadToEnd()

{

return File.ReadAllText(FileName);

}

}

Now, we’ll register two components with the container, each one reading a different file.

component “file1.reader”, FileReader:

FileName=”file1.txt”

component “file2.reader”, FileReader:

FileName=”file2.txt”

Finally, the program code:

static void Main(string[] args)

{

FileReader defaultReader = container.Resolve<FileReader>();

FileReader file1Reader = container.Resolve<FileReader>(“reader.file1”);

FileReader file2Reader = container.Resolve<FileReader>(“reader.file2”);

Console.WriteLine(“Default contents: {0}”, defaultReader.ReadToEnd());

Console.WriteLine(“File1 contents: {0}”, file1Reader.ReadToEnd());

Console.WriteLine(“File2 contents: {0}”, file2Reader.ReadToEnd());

}

Adding the text files and running this bad boy gives the output:

Default contents: This is the contents of file 1
File1 contents: This is the contents of file 1.
File2 contents: This is the contents of file 2.

So, as Alex says, the default implementation is the first one in the file, just like using XML.

In his tutorial, Alex gives another example of why you would need to reference implementations by id, so if you’re interested, you can read it there (although, you shoulda already read that post…right?)

Next time, constructor injection…


The Bitter Coder Tutorials, Binsor Style VII: Switching Implementations

Previous posts in the series:

In tutorial #7, Alex shows us the real meat of DI, which is switching out implementations.  This is where I had my “A-HA!” moment with Windsor and where I continue to see the most obvious value.

As Alex states, when switching implementations, you take the contract of your implementation and stuff it in an interface.  Here’s the interface for our example:

public interface IMessageOfTheDay

{

string GetMessageOfTheDay();

}

And the same two implementations from Alex:

public class StaticMessageOfTheDay:IMessageOfTheDay

{

private string _message;

public string Message

{

set { _message = value; }

}

public string GetMessageOfTheDay()

{

return _message;

}

}

And #2:

public class WikiQuotesMessageOfTheDay : IMessageOfTheDay

{

public string GetMessageOfTheDay()

{

WebClient client = new WebClient();

string content = client.DownloadString(http://en.wikiquote.org/wiki/Main_Page&#8221;);

string toFind = “<td align=\”center\”>”;

int start = content.IndexOf(toFind) + toFind.Length + 56;

int length = content.IndexOf(“<a”, start) – start;

return content.Substring(start, length);

}

}

(I had to change the string that Alex was searching on and hardcode a length to the beginning of the quote, so maybe I’ll rename this class to HorrificQuoteOfTheDay or something)

So, let us get to the Binsor config.  First off, I put my interface in a separate namespace, so I had to add an import clause to the top of the Windsor.boo file.  Then, I add the StaticMessageOfTheDay component:

import BitterCoder.Tutorials.Binsor.Core.Interfaces

component “motd.service”,IMessageOfTheDay,StaticMessageOfTheDay:

message=”Welcome to my Binsor tutorials”

Now, when I run the project, I get:

MOTD: Welcome to my Binsor tutorials

Changing out the motd.service component for the Wiki Quotes:

component “motd.service”,IMessageOfTheDay,WikiQuotesMessageOfTheDay

The running program now gives:

MOTD: Those works of art which have scooped up the truth and presented it to us
as a living force â?” they take hold of us, compel us, and nobody ever, not even
in ages to come, will appear to refute them. ~

It’s just that easy.  Our quote is from Aleksandr Solzhenitsyn, whom I can safely say I’ve never heard of before, but I will take as a sign that this blog post is a work of art.

Next time, switching implementations by id….


The Bitter Coder Tutorials, Binsor Style VI: Switching Lifestyles

Previous posts in the series:

In tutorial #6, Alex discusses lifestyles and how to muck about with them.  If you are unfamiliar with what lifestyles are in this context, go read his post first (which you should be doing anyway)

So, we create the same adding service component (minus the spelling errors ;)):

public class AddingService

{

private int _total = 0;

public void AddAmount(int amount)

{

_total += amount;

}

 

public int Total

{

get { return _total; }

}

}

And we add it to the Windsor configuration, like so:

component “adding.service”, AddingService

Nothing special.  When we run the code we get:

You have counted 75 sheep and herded 75 angry cats

This seems a bit odd, as the container is using the same instance for both AddingService requests.  Let’s make it give us a new one for each request.  This is accomplished by adding the “lifestyle” attribute to the component:

component “adding.service”, AddingService:

@lifestyle=”transient”

Notice the “@” sign, which tells Binsor to put this attribute on the Windsor component, but not the class instance (I can’t figure out a better way to word that.)  Now, when we run it, we get:

You have counted 60 sheep and herded 15 angry cats

Snot on.  Alex goes on to say how you can add an attribute on the class to indicate it’s lifestyle.  That isn’t really relevent to what I’m doing here, but you should check it out all the same.

Coming up….Switching Implementations, which is where a DI container really starts to make sense.