Category Archives: Castle

WCF and Castle Windsor Update

My old post about the Castle Windsor WCF facility is a bit long in the tooth, as Mr. Craig Neuwirt and others have been hard at work improving the facility.  The release of Windsor 2.0 inspired me to attempt to go over the facility and highlight some of the new items.  In the process, I’ll cover some basics, as even those have changed a bit.   I have written most of the new documentation for the WCF facility, which needs to be reviewed by Craig since some of the new stuff is above my pay grade.  The good news is that, when released, the facility will have some good documentation as well.

The best place to see the new facility in action is to grab Castle’s trunk and go thorugh the WCF Facility unit tests.  They are comprehensive and give a great example of the new features of the facility.  This post, and the documentation I wrote, are almost entirely based on those tests.  Now, on to some examples.

Basic Server Quick Start

The basic steps to using the WCF Facility are the same, and consist of:

  1. Create your WCF service and data contracts.
  2. Create a service type, implementing your contract.
  3. Create your .svc file for your service.
  4. Configure Windsor to use the WCF Facility for your service.

Create WCF Service and Data Contracts

In this very simple example, I am only going to use a service contract.  Here is my contract:

namespace MyService.Core.Interfaces

{

[ServiceContract]

public interface IMyService

{

[OperationContract]

string MyOperation1(string myValue);

}

}

Reblog this post [with Zemanta]So, all my operation contract does is take in a string and return a string. No big whoop.

Implement the Contract

namespace MyService.Core

{

public class TheService : IMyService

{

public string Prefix { get; set; }

public TheService(string prefix)

{

Prefix = prefix;

}

 

#region IMyService Members

public string MyOperation1(string myValue)

{

return String.Format(“{0} {1}”,Prefix, myValue);

}

#endregion

}

}

Create your SVC file

Presuming you have a web application to host your service, all raring to go, we need to tell the framework how to creaate your service.  That’s what the .svc file does:

<%@ ServiceHost Service="my service"
Factory="Castle.Facilities.WcfIntegration.DefaultServiceHostFactory, Castle.Facilities.WcfIntegration" %>

As with the previous version of the facility, you have to use a custom ServiceHostFactory, which has changed to Castle.Facilities.WcfIntegration.DefaultServiceHostFactory.  Also, the Service attribute in the .svc file needs to point to the component name in your Windsor configuration, which brings us to…

Configure Windsor

In my last post, I used Boo to configure the container.  This time around, I am going to use the fluent API that Craig has created because it is kick ass.  The container needs to be configured on application start, so we put the following in the Global.asax file:

#region IContainerAccessor Members

public IWindsorContainer Container { get; private set; }

#endregion

 

protected void Application_Start(object sender, EventArgs e)

{

ServiceMetadataBehavior metadata = new ServiceMetadataBehavior();

metadata.HttpGetEnabled = true;

 

Container = new WindsorContainer()

.AddFacility<WcfFacility>()

.Register(

Component.For<IServiceBehavior>().Instance(metadata),

Component.For<IMyService>()

.Named(“my service”)

.ImplementedBy<TheService>()

.DependsOn(new {prefix = “A WCF Facility Service says”})

);

}

Here, lemme ‘splain.  As with any web application that uses Windsor, the container lives on the Global Application object.   Here, I first add the WcfFacility followed by adding a service behavior (ServiceMetadataBehavior).  This behavior will be added to all services registered with the container, however, new to the facility is the ability to explicitly scope a behavior.  You can scope a behavior to:  all services, all clients, or to explicit clients/services.  I know that feature was oft-requested by the community and Craig is the man for getting it done.  Back to our example, the service is registered is a IMyService named “my service” (remember our .svc file) and implemented by the TheService type.  Finally, I pass in my constructor argument, which is a string.  Oh, and in order to use the facility, you’ll need a reference to the following assemblies:

  • Castle.Core
  • Castle.Windsor
  • Castle.MicroKernel
  • Castle.Facilities.WcfIntegration
  • Castle.DynamicProxy2

That’s it!   The service is ready to run.  You’ll notice (or maybe you didn’t), that I did not even open the web.config.  You can use the web.config if you like, but I didn’t here because I am lazy.  You also may have noticed that I did not specify an endpoint or binding, so the facility created a default endpoint with BasicHttpBinding.  Again, I am lazy, but that is cool.

Show Me the Service

The image here shows what the service looks like in the WCFTestClient.exe application.

Easy peasy

Easy peasy

The default protocol is SOAP (does anyone use SOAP anymore?) but you could easily create a REST endpoint.  Maybe I’ll show that in my next post about this stuff.   This post only covers the very basics, so if you have more complicated stuff, I can take a stab at it or maybe ask Craig.

Just to be complete, here are most of the  big time new features:

  • Scoped Behaviors
  • The ability to create service hosts and control the host life cycle (see IServiceHostAware)
  • Fluent API

Speaking of which, lemme know if there is anything specific you want to see concerning the WCF Facility.  As I mentioned, the unit tests in the castle trunk are pretty comprehensive and the forthcoming documentation will have tons of configuration examples.  Try it out, it makes managing dependencies with WCF a breeze.

Advertisements

The Bitter Coder Tutorials, Binsor Style: XIV Startable Facilities

Previous posts in the series:

The last (until Alex writes more) of our Bitter Binsor tutorials is here.  Today, we focus on the Startable Facility, which is explained in Alex’s post.  The link to the wiki in Alex’s post is no good, so try here for more info on the facility.  Basically, something is startable if it has the Start/Stop controllable lifecycle, like a web server.  In Castle, to be considered Startable you have to implement the IStartable interface:

/// <summary>

/// Interface for components that wish to be started by the container

/// </summary>

public interface IStartable

{

/// <summary>

/// Starts this instance.

/// </summary>

void Start();

/// <summary>

/// Stops this instance.

/// </summary>

void Stop();

}

Once you register the Startable Facility with the Windsor Container, it will attempt to create and call .Start() on any startable component, provided all the dependencies have been satisfied.  So, every time a component is registered with the container, Windsor checks to see if a startable component has all dependencies satisfied and can be started.  Alex discusses the startable facility more in his post, so make sure you read it too.
Let’s create the LameHttpServer using this code:

public class LameHttpServer:IStartable

{

private string _path;

private HttpListener _listener;

private Thread _listenerThread;

private ILogger _logger;

public ILogger Logger

{

get

{

if (_logger == null)

_logger = NullLogger.Instance;

return _logger;

}

set { _logger = value; }

}

public LameHttpServer(string prefix, string path)

{

_path = path;

_listener= new HttpListener();

_listener.Prefixes.Add(prefix);

}

public void Start()

{

Logger.Debug(“Starting LameWebService…”);

_listener.Start();

_listenerThread = new Thread(RequestWorker);

_listenerThread.Start();

Logger.Info(“LameWebService started…”);

}

public void Stop()

{

Logger.Debug(“Stopping LameWebService…”);

_listenerThread.Abort();

_listener.Stop();

Logger.Info(“LameWebService stopped.”);

}

private void RequestWorker()

{

while (true)

{

HttpListenerContext _context = null;

try

{

_context=_listener.GetContext();

} catch (ObjectDisposedException ex)

{

return;

}

ServeContext(_context.Response, _path);

}

}

private void ServeContext(HttpListenerResponse response, string _path)

{

string content = File.ReadAllText(_path);

byte[] buffer = Encoding.UTF8.GetBytes(content);

response.ContentLength64 = buffer.Length;

Stream output = response.OutputStream;

output.Write(buffer, 0 , buffer.Length);

output.Close();

}

}

Looking at the class, we need a couple of configuration parameters as well as a dependency on  ILogger.  We’ll use the Castle Logging Facility for that, which is probably the facility I use most.  You should check it out.  Anyway, here’s our Binsor:
facility "startable.facility", StartableFacility

facility "logging.facility",LoggingFacility:
  loggingApi=LoggerImplementation.Console

component "lame.http", LameHttpServer:
    prefix="http://*:8089/"
    path="lame.html"

So, we register the facilities discussed earlier.  BTW, in order to resolve the facilities, I had to add the following to the top of Windsor.boo, in the import section:

import Castle.Facilities.Startable from Castle.MicroKernel
import Castle.Facilities.Logging

Also, I added  a reference to the Castle.Facilites.Logging assembly.  I already had a reference for Castle.MicroKernel from a previous post.

Let’s look at our console code to crank up the server:

public static void Main(string[] args)

{

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

GetPage();

container.Dispose();

GetPage();

}

private static void GetPage()

{

Console.WriteLine(“\r\nClient: requesting http://localhost:8089/…&#8221;);

try

{

WebClient client = new WebClient();

string content = client.DownloadString(http://localhost:8089/&#8221;);

Console.WriteLine(“Client: success, content follows.\r\n\r\n {0}”, content);

} catch (WebException ex)

{

Console.WriteLine(“Client: Exception occurred, message {0}”,ex.Message);

}

}

So, as can be seen above, we

  1. Create the container, which kicks off the server, coz it’s all Startable and stuff.
  2. Call GetPage().
  3. Dispose of the conatainer.
  4. Call GetPage() again.
  5. Wonder aloud of Alex minds plagiarism.

Here’s the results:

[Debug] 'BitterCoder.Tutorials.Binsor.Core.LameHttpServer' Starting LameWebService...
[Info] 'BitterCoder.Tutorials.Binsor.Core.LameHttpServer' LameWebService started...

Client: requesting http://localhost:8089/...
Client: success, content follows.

 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
        <head>
                <title></title>
        </head>
        <body>
             <h1>Lame.html</h1>
        <h2>Welcome to lame.html file</h2>
        <p>This is the contents of the lame.html file, neat huh?</p>
        </body>
</html>
[Debug] 'BitterCoder.Tutorials.Binsor.Core.LameHttpServer' Stopping LameWebService...
[Info] 'BitterCoder.Tutorials.Binsor.Core.LameHttpServer' LameWebService stopped.

Client: requesting http://localhost:8089/...
Client: Exception occurred, message Unable to connect to the remote server

The error at the end of the results is due to us disposing of the container, which decommisions all the components in the container.  Alex explains this well…so read what he said.

So, I am gonna modify Alex’s final example where he demonstrates lifestyles and their effect on Startable facilities.  The only difference, really, is I am  going to show you what the Binsor looks like to control the lifestyle of a component.

Here’s our StartableExperiment:

public class StartableExperiment : IStartable

{

private static int _count;

private readonly int _number;

public StartableExperiment()

{

_number = ++_count;

}

#region IStartable Members

public void Start()

{

Console.WriteLine(“Started #{0}”, _number);

}

public void Stop()

{

Console.WriteLine(“Stopped #{0}”, _number);

}

#endregion

}

And the Binsor:

component "startable.exp", StartableExperiment:
    @lifestyle=LifestyleType.Transient

(You need to import Castle.Core to get the LifestyleType enum)

Running the following program code:

StartableExperiment exp1 = container.Resolve<StartableExperiment>();

container.Release(exp1);

StartableExperiment exp2 = container.Resolve<StartableExperiment>();

container.Release(exp2);

yields:

Started #1
Started #2
Stopped #2
Started #3
Stopped #3
Stopped #1

If I change the @lifestyle attribute in the Binsor to LifestyleType.Singleton, I get:

Started #1
Stopped #1

And that’s Startable Facilities and their lifestyles, from a Binsor point-of-view.

So, I hope someone enjoyed the series.  Thanks again to Alex for his tutorials.  They were a big rung in my learning ladder for Windsor.

I created a VS.NET project with all the code from this series.  If you’re interested, hit me at glenn(dot)goodrich(at)gmail.com.


The Bitter Coder Tutorials, Binsor Style: Injecting Service Arrays

Previous posts in the series:

This post feeds off off Part 12 and is based on Alex’s post here.  We are going to rework the last post and remove the decorator pattern.  Instead, we’ll create a calculator that manages any number of other calculators, which are injected as an array.

So, in keeping with my shameless plagirizing of Alex’s code, here is the abstract class for our new calculators:

namespace BitterCoder.Tutorials.Binsor.Core

{

public abstract class AbstractCalculator

{

public abstract decimal Calculate(decimal currentTotal, Order order);

}

}

And now our total calculator:

using System.Linq;

 

namespace BitterCoder.Tutorials.Binsor.Core

{

public class TotalCalculator : AbstractCalculator

{

private static decimal CalculateTotal(Order order)

{

return order.Items.Sum(item => item.CostPerItem*item.Quantity);

}

 

public override decimal Calculate(decimal currentTotal, Order order)

{

return currentTotal + CalculateTotal(order);

}

}

}

And the GST calculator:

namespace BitterCoder.Tutorials.Binsor.Core

{

public class GSTCostCalculatorNoDecorator : AbstractCalculator

{

private decimal _gstRate = 1.125m;

 

public decimal GstRate

{

get { return _gstRate; }

set { _gstRate = value; }

}

 

private static bool IsNewZealand(Order order)

{

return (order.CountryCode == “NZ”);

}

 

public override decimal Calculate(decimal currentTotal, Order order)

{

if (IsNewZealand(order))

{

return (currentTotal*_gstRate);

}

return currentTotal;

}

}

}

The shipping calculator:

namespace BitterCoder.Tutorials.Binsor.Core

{

public class ShippingCalculatorNoDecorator : AbstractCalculator

{

private decimal _fragileShippingPremium = 1.5m;

private decimal _shippingCost = 5.0m;

 

public decimal ShippingCost

{

get { return _shippingCost; }

set { _shippingCost = value; }

}

 

public decimal FragileShippingPremium

{

get { return _fragileShippingPremium; }

set { _fragileShippingPremium = value; }

}

 

private decimal GetShippingTotal(Order order)

{

decimal shippingTotal = 0;

return order.Items.Sum(item =>

{

decimal itemShippingCost = ShippingCost*item.Quantity;

if (item.IsFragile) itemShippingCost *= FragileShippingPremium;

return shippingTotal += itemShippingCost;

});

}

 

public override decimal Calculate(decimal currentTotal, Order order)

{

return currentTotal + GetShippingTotal(order);

}

}

}

Lastly, our calculator of calculators, the reworked DefaultCalculator:

public class DefaultCalculatorNoDecorator : ICostCalculator

{

private readonly AbstractCalculator[] _calculators;

 

public DefaultCalculatorNoDecorator(AbstractCalculator[] _calculators)

{

this._calculators = _calculators;

}

 

 

public decimal CalculateTotal(Order order)

{

decimal currentTotal = 0;

 

return _calculators.Sum(calc => calc.Calculate(currentTotal, order));

}

}

 

So, we’ll inject an array of calculators (total, shipping, and gst) into our default calculator. Binsor, away!

component "default.calculator", ICostCalculator,DefaultCalculatorNoDecorator:
    _calculators=[@total.calculatornodec,@shipping.calculatornodec,@gst.calculatornodec]

component "total.calculatornodec", AbstractCalculator,TotalCalculator

component "gst.calculatornodec", AbstractCalculator, GSTCostCalculatorNoDecorator:
    GstRate=Convert.ToDecimal(1.20)

component "shipping.calculatornodec", AbstractCalculator, ShippingCalculatorNoDecorator:
    FragileShippingPremium=Convert.ToDecimal(0.0)

Just like we did in our post on arrays, we inject an array of dependencies.  Changing the order is just a matter of switching the order in the binsor.  All good.

Running the program gives the same output as the last post.

Next post, which is the last in the series until Alex writes more (whew), is on the “Startable” facility.

Reblog this post [with Zemanta]

The Bitter Coder Tutorials, Binsor Style: Part XII, Decorators

UML Class diagram of the decorator pattern

Image via Wikipedia

Previous posts in the series:

Today’s post focuses on Decorators.  The Decorator Pattern is a well-known design pattern where functionality is added to a class by wrapping it with another class.  Like an onion, sorta.  Anyway, copying Alex, we are going to use this pattern with Windsor to chain implementations together.

Here is our Order and OrderItem classes:

public class Order

{

private readonly List<OrderItem> _items = new List<OrderItem>();

public List<OrderItem> Items

{

get { return _items; }

}

public string CountryCode { get; set; }

}

public class OrderItem

{

public OrderItem(string name, int quantity, decimal costPerItem, bool isFragile)

{

Name = name;

Quantity = quantity;

CostPerItem = costPerItem;

IsFragile = isFragile;

}

public bool IsFragile { get; set; }

public int Quantity { get; set; }

public decimal CostPerItem { get; set; }

public string Name { get; set; }

}

And an interface to calculate the cost of an order:

public interface ICostCalculator

{

decimal CalculateTotal(Order order);

}

Our default cost calculator (Side note: I like LINQ):

public class DefaultCostCalculator:ICostCalculator

{

public decimal CalculateTotal(Order order)

{

return order.Items.Sum(ord => ord.CostPerItem*ord.Quantity);

}

}

Our Binsor for the DefaultCostCalculator:

component "default.calculator", ICostCalculator,DefaultCostCalculator

Now, the program itself:

static void Main(string[] args)

{

var order1 = new Order

{

CountryCode = “NZ”,

Items =

{

new OrderItem(“water”, 10, 1.0m, false),

new OrderItem(“glass”, 5, 20.0m, true)

}

};

var order2 = new Order

{

CountryCode = “US”,

Items =

{

new OrderItem(“sand”, 50, 0.2m, false)

}

};

var _calc = container.Resolve<ICostCalculator>();

Console.WriteLine(“Cost to deliver Order 1: {0}”, _calc.CalculateTotal(order1));

Console.WriteLine(“Cost to deliver Order 2: {0}”, _calc.CalculateTotal(order2));

}

Running the program, gives us:

Cost to deliver Order 1: 110.0
Cost to deliver Order 2: 10.0

Now, let’s go to New Zealand where we have to pay the Goods and Services Tax.  Here is our cost calculator for that:

public class GstCostCalcualtorDecoarator : ICostCalculator

{

private readonly ICostCalculator _innerCalculator;

private decimal _gstRate = 1.125m;

public GstCostCalcualtorDecoarator(ICostCalculator innerCalculator)

{

_innerCalculator = innerCalculator;

}

public decimal GstRate

{

get { return _gstRate; }

set { _gstRate = value; }

}

#region ICostCalculator Members

public decimal CalculateTotal(Order order)

{

decimal innerTotal = _innerCalculator.CalculateTotal(order);

if (IsNewZealand(order))

{

innerTotal = (innerTotal*_gstRate);

}

return innerTotal;

}

#endregion

private bool IsNewZealand(Order order)

{

return (order.CountryCode == “NZ”);

}

}

And here’s the Decorator pattern.  The GstCostCalculatorDecorator class accepts another ICostCalculator, then modifies the result by adding the GST.  The DefaultCostCalculator is clueless to the GST, which is the beauty inherit in the pattern.

Let’s wire up the Binsor:

component "gst.calculator", ICostCalculator, GstCostCalculatorDecorator:
    innerCalculator=@default.calculator

component "default.calculator", ICostCalculator,DefaultCostCalculator

We put the GST calculator first, so it’s the default implementation, and run the program:

Cost to deliver Order 1: 123.7500
Cost to deliver Order 2: 10.0

So, the US one hasn’t changed, as expected.  Finally, let’s add a shipping calculator:

public class ShippingCostCalculatorDecorator : ICostCalculator

{

private readonly ICostCalculator _innerCalculator;

public decimal ShippingCost { get; set; }

public decimal FragileShippingPremium { get; set; }

public ShippingCostCalculatorDecorator(ICostCalculator innerCalculator)

{

_innerCalculator = innerCalculator;

ShippingCost = 5.0m;

FragileShippingPremium = 1.5m;

}

#region ICostCalculator Members

public decimal CalculateTotal(Order order)

{

decimal innerTotal = _innerCalculator.CalculateTotal(order);

return innerTotal + GetShippingTotal(order);

}

#endregion

private decimal GetShippingTotal(Order order)

{

return order.Items.Sum(item =>

{

var itemShippingCost = ShippingCost*item.Quantity;

if (item.IsFragile) itemShippingCost *= FragileShippingPremium;

return itemShippingCost;

});

}

}

And add our Binsor, making sure it’s the first ICostCalculator implementation in the file:

component "shipping.calculator", ICostCalculator, ShippingCostCalculatorDecorator:
    innerCalculator=@gst.calculator

Run it.

Cost to deliver Order 1: 211.2500
Cost to deliver Order 2: 260.0

As Alex points out, we are calculating our GST before shipping, which is kinda stoopid.  The Decorator Pattern saves our bacon here, as we can just swap things around (oh, and we change some parameters too):

component "gst.calculator", ICostCalculator, GstCostCalculatorDecorator:
    innerCalculator=@gst.calculator
    GstRate=1.20

component "shipping.calculator", ICostCalculator, ShippingCostCalculatorDecorator:
    innerCalculator=@default.calculator
    FragileShippingPremium=0.0

component "default.calculator", ICostCalculator,DefaultCostCalculator

Run it one more time:

Cost to deliver Order 1: 211.2500
Cost to deliver Order 2: 260.0

So, that’s that.  Alex has some great comments in his post about other stuff you can do with the Decorator pattern, so I highly recommend you read his all the way through.

Next time we’ll do this stuff without decorators….

Reblog this post [with Zemanta]

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.


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!