Monthly Archives: September 2008

The Bitter Coder Tutorials, Binsor Style: Part XI, Factories

Previous posts in the series:

In this post, I will be discussing how to use Binsor to configure the factory support facility in Windsor.  A “facility” is (as Alex states) an add-in to the Windsor container that changes or adds what the container can do.  Facilities are a big part of what makes Windsor so freaking kick-ass, and other facilities are the logging facility, the transaction facility, and (the oft blogged about here) WCF facility.

So, let’s get to the code.  Here’s our interface:

public interface ISmsService

{

void SendMessage(string number, string message);

}

And our SmsService and SmsConfig classes:

public class SmsService : ISmsService

{

private SmsConfig _config;

 

public void SetConfig(SmsConfig config)

{

_config = config;

}

 

public void SendMessage(string number, string message)

{

Console.WriteLine(“SMS Message: {0} sent to {1} with account {2}”, message, number, _config.UserName);

}

}

public class SmsConfig

{

 

private string _userName;

private string _password;

private int _retryAttempts{ get; set;}

 

internal string UserName

{

get { return _userName; }

}

 

internal string Password

{

get { return _password; }

 

}

 

public void SetCredentials(string user, string pwd)

{

_userName = user;

_password = pwd;

}

}

Now, showing what is necessary to instantiate our SmsService class:

SmsService service = new SmsService();

 

SmsService.SmsConfig config = new SmsService.SmsConfig();

config.SetCredentials(“joe”, “secret”);

config.RetryAttempts = 3;

 

service.SetConfig(config);

That is not gonna work with Windsor straight away.  So, we need a factory to take care of this for us:

public class SmsServiceFactory

{

private string _userName;

private string _password;

private int _retryAttempts { get; set; }

 

public SmsServiceFactory(string userName, string password)

{

this._userName = userName;

this._password = password;

_retryAttempts = 3;

}

 

public ISmsService CreateService()

{

SmsService service = new SmsService();

SmsConfig config = new SmsConfig();

config.SetCredentials(_userName,_password);

service.SetConfig(config);

 

return service;

}

}

Right.  Now we have to get our supporting Binsor squared away.  First off, let’s register the facility.  Add the following import statement to the top of your .boo file:

import Castle.Facilities.FactorySupport from Castle.MicroKernel

So, Binsor knows where to get the facility.  Then, the facility itself:

facility FactorySupportFacility

Now we have to add our factory and our component:

component "smsservice.factory", SmsServiceFactory:
    userName="joe"
    password="secret"

component "smsservice.default", ISmsService,SmsService:
    @factoryId=@smsservice.factory
    @factoryCreate="CreateService"

Last, but not least, the program:

private static void Main(string[] args)

{

container = new WindsorContainer().Install(BinsorScript.FromFile(“windsor.boo”));

ISmsService smsService = container.Resolve<ISmsService>();

smsService.SendMessage(“+465556555”, “testing testing…1.2.3”);

Console.Read();

}

Running the console, gives us:

SMS Message: testing testing…1.2.3 sent to +465556555 with account joe

Seems we’re looking at the Decorator Pattern with Windsor next…

Reblog this post [with Zemanta]

The Bitter Coder Tutorials Binsor Style, Part X: Setter Injection

Previous posts in the series:

So, we’re 10 posts into our arguable plagerism of Alex’s tutorials, and this post’s focus is setter injection.  Setter injection is, basically, exposing a class’s dependencies via properties, as opposed to constructor parameters.  I prefer setter injection only when the number of dependencies is very high, and in most of those cases, it’s probably code smell.  However, we are just here to Binsorify the Bitter Coder Tutorials, so off we go.

We are slightly refactoring the project from Part 9, adding the ability to specify a formatter for our encoded message.  The interface is here:

public interface IMessageFormatter

{

string FormatMessage(string from, string to, string body);

}

Here’s the default formatter:

public class DefaultFormatter:IMessageFormatter

{

public string FormatMessage(string from, string to, string body)

{

return string.Format(“to: {0}\r\nfrom: {1}\r\n\r\n{2}”, to, from, body);

}

}

And the refactored version of last post’s message sender, incorporating our new dependency:

public class SecretMessageSender

{

private readonly IEncoder _encoder;

private readonly string _from;

public SecretMessageSender(IEncoder _encoder, string _from)

{

this._encoder = _encoder;

this._from = _from;

}

public void SendMessage(string to, string body)

{

Console.WriteLine(“to: {0}\r\nfrom: {1}\r\n\r\n{2}”, to, _from, _encoder.Encode(body));

}

}

Looking at the config now, we have:

component “default.formatter”, IMessageFormatter, DefaultFormatter

component “messageformat.sender”, FormatMessageSender:

_from=”ruprict@wordpress.com”

_encoder=@null.encoder

Notice that we don’t specifically set the Formatter in the config, so Windsor will do that for us.  Running the program now will yield the same results as the last post.  Keeping with Alex’s tutorial, let’s make another formatter, this one based on the NVelocity template engine.  NVelocity has changed a good bit since Alex used it in his tutorial, so the code is a bit more complex (thanks for the help on this, Alex):

public class NVelocityMessageFormatter : IMessageFormatter

{

private readonly Template _template;

private readonly VelocityEngine _velocity;

public NVelocityMessageFormatter(string _templateFile)

{

_velocity = new VelocityEngine();

var props = new ExtendedProperties();

props.SetProperty(RuntimeConstants.RESOURCE_LOADER, “file”);

props.SetProperty(RuntimeConstants.FILE_RESOURCE_LOADER_PATH,

Path.GetDirectoryName(Assembly.GetExecutingAssembly().GetModules()[0].FullyQualifiedName));

props.SetProperty(RuntimeConstants.FILE_RESOURCE_LOADER_CACHE, “false”);

_velocity.Init(props);

_template = _velocity.GetTemplate(_templateFile);

}

#region IMessageFormatter Members

public string FormatMessage(string from, string to, string body)

{

var context = new VelocityContext();

context.Put(“from”, from);

context.Put(“to”, to);

context.Put(“body”, body);

context.Put(“today”, DateTime.Now);

var writer = new StringWriter();

_template.Merge(context, writer);

return writer.ToString();

}

#endregion

}

Our formatter merges the parameters (from, to, and body) with the template, which looks like:

To:   $to

From: $from

Sent: $today

———————-

$body

———————-

Finally, let’s see how we configure the program to use our fancy new formatter:

component “fancymessage.formatter”, IMessageFormatter, NVelocityMessageFormatter:

_templateFile=”message.vm”

component “messageformat.sender”, FormatMessageSender:

_from=”ruprict@wordpress.com”

_encoder=@null.encoder

Formatter = @fancymessage.formatter

We specify the template file as well as the “Formatter” parameter.  Our output now looks like:

To:   hammett
From: ruprict@wordpress.com
Sent: 8/25/2008 9:49:39 AM
———————-

Howzit going at Microsoft?

———————-
And we’re done.  We covered a decent amount of stuff in this post: setter injection, default dependencies, overriding default dependencies, as well as how to use NVelocity as a template engine.

Next time….factories.