# Wednesday, August 12, 2009

So I decided to take the Horn project for a test drive after repaving a number of machines to Windows 7 RTM and waiting for things to install.

After Horn’s initial announcement this year I was excited, but it didn’t really do anything at that stage (and I didn’t have enough time to assist with the dev work / patches)... so I put it on the back burner.  But I found myself need to rebuild Rhino Tools, Castle and NHibernate today from trunk and thought I would give it a try.

At any rate, this is a post covering my “noob” observations as I walk through building horn, and then using horn to build Rhino Tools.

Background

As a little background, Horn was started by the Scotland ALT.Net group, it was kicked off on the scotaltdotnet google code project, and later moved to the hornget project, also on google code. The projects Initial mission statement is to “take control of building a common set of open source packages that are probably similar to many in the ALT.NET space” which I think it’s coming close to realising, but they also have a grander vision of “providing a standard mechanism for easy installation of .Net Packages” – something I definitely think .Net needs, and that dynamic languages lord over us currently with their gem’s and egg’s (and incidentally it is a much trickier problem to solve when you need to produce compiled assemblies, think signing vs. unsigned, ability to specify x86/x64/any platform flags and the way in which assembly versioning in .Net works).

Building Horn

Assuming you have the Subversion command line tools installed (or tortoise svn) - it’s pretty easy.  First off check out the horn trunk…

svn checkout http://hornget.googlecode.com/svn/trunk/ hornget-read-only

Once all the files have been pulled down, you need to then build horn, using the following batch file:

cd hornget-read-only\src
hornbuild.bat

hornbuild.bat will execute Nant, and the total build takes about 15 to 20 seconds. It dumps the outputs into a \build\net-3.5\debug\ folder, including horn.exe which is the command line client (Horn package manager).  I would assume as Horn matures we will see an installer / binary release on the horn website, which should hopefully make this even easier.

Running Horn

Now jump into the outputs directory...and run horn for the first time.

cd build\net-3.5\debug\
horn

At which point you will be rewarded with the usage screen:

THE HORN PACKAGE MANAGER

http://code.google.com/p/hornget/

Usage : horn -install:
Options :
    -rebuildonly     Do not check for the latest source code.
    -version:        The specific version of a package.

Now it's just a matter of building the project you want.. in this case let's build rhino tools (which in turn will build Nhibernate and some parts of the castle project).  Might pay to go make a coffee at this point, as there's going to be a lot going on while you wait patiently.

horn -install:rhino

Oh, and expect to see a lot of this if your connection to the various project’s SVN repositories is slow..

Reading the current revision for castle
working......
working......
working......
working......
working......
working......
working......
working......
working......
working......

Also, as an aside - there's a cyclic relationship between Castle and NHibernate (i.e. Nhibernate relies on Castle Core & Dynamic Proxy, while Castle relies on NHibernate to build) - it's not truly cyclic as such though, just that if you attempt to build either set of project in it's entirety, you will need the outputs of the other. In Horn things like dynamic proxy are broken out into separate projects ie. "castle.tools" rather then just "castle" (though a castle package exists as well, which does build castle in it’s entirety).

It seems to handle this scenario well, and this was certainly a failing of most home-grown solutions I’ve put together over the years which relied on nant or msbuild files… Right, so after about 5 minutes, you should see the horn executable run to completion, like this:

BUILD SUCCEEDED

Total time: 46.6 seconds.


HORN HAS FINISHED INSTALLING rhino.

Note: The "BUILD SUCCEEDED" message is from rhino tools, which was the last project to be built, rather then telling us how long the process took in total.

Locating Outputs

At this point Horn has finished doing it's job, but... if you do a quick directory search, you probably won't find any output binaries. What gives? Well Horn in fact stores all it's files under a directory against the user's profile. So in the case of windows 7 / Vista, that means I can just change directory to find them:

c:\dev\OtherOpenSource\hornget-read-only\src\build\net-3.5\debug>cd %USERPROFILE%\.horn

C:\Users\alex\.horn>_

If we grab a quick directory listing... we can see there's a few folders in there.

C:\Users\alex\.horn>dir * /A
 Volume in drive C has no label.
 Volume Serial Number is 6AFA-976C

 Directory of C:\Users\alex\.horn

12/08/2009  09:39 p.m.    <DIR>          .
12/08/2009  09:39 p.m.    <DIR>          ..
12/08/2009  09:37 p.m.    <DIR>          .svn
10/08/2009  03:47 p.m.    <DIR>          buildengines
10/08/2009  03:47 p.m.    <DIR>          builders
10/08/2009  03:47 p.m.    <DIR>          esbs
10/08/2009  03:46 p.m.    <DIR>          frameworks
10/08/2009  03:47 p.m.    <DIR>          ioc
10/08/2009  03:46 p.m.    <DIR>          languages
10/08/2009  03:46 p.m.    <DIR>          loggers
10/08/2009  03:46 p.m.    <DIR>          mappers
10/08/2009  03:47 p.m.    <DIR>          mocks
10/08/2009  03:47 p.m.    <DIR>          orm
12/08/2009  09:45 p.m.    <DIR>          result
12/08/2009  09:37 p.m.                15 revision.horn
10/08/2009  03:47 p.m.    <DIR>          web
10/08/2009  03:47 p.m.    <DIR>          wpf
               1 File(s)             15 bytes
              16 Dir(s)  578,876,366,848 bytes free

Notice the .svn folder, the .horn directory is actually populated from this subversion repository, which stores all the package descriptions etc. (I’m not entirely clear on the terminology here, documentation is fairly sparse on the website – they’re almost more like package build scripts, because they’re a DSL outlining the steps required to build the outputs, required dependencies and so on).

The one folder not under version control is "result" - which is where our outputs are actually stored. So let's take a quick look...

C:\Users\alex\.horn>cd result

C:\Users\alex\.horn\result>dir
 Volume in drive C has no label.
 Volume Serial Number is 6AFA-976C

 Directory of C:\Users\alex\.horn\result

12/08/2009  09:45 p.m.    <DIR>          .
12/08/2009  09:45 p.m.    <DIR>          ..
10/08/2009  03:56 p.m.             1,997 ABC.hbm.xml
10/08/2009  03:48 p.m.           110,592 adodb.dll
10/08/2009  04:07 p.m.               568 AnotherBus.config
10/08/2009  03:48 p.m.            40,960 anrControls.Markdown.NET.dll
10/08/2009  03:58 p.m.           106,496 antlr.runtime.dll
10/08/2009  04:01 p.m.           116,736 Antlr3.Runtime.dll
10/08/2009  03:59 p.m.            40,960 Bamboo.Prevalence.dll
10/08/2009  03:59 p.m.             6,656 Bamboo.Prevalence.Util.dll
10/08/2009  04:01 p.m.            40,960 Boo.Lang.CodeDom.dll
10/08/2009  04:01 p.m.           753,664 Boo.Lang.Compiler.dll
10/08/2009  04:01 p.m.           118,784 Boo.Lang.dll
10/08/2009  04:01 p.m.            32,768 Boo.Lang.Extensions.dll
10/08/2009  04:01 p.m.            86,016 Boo.Lang.Interpreter.dll
10/08/2009  04:01 p.m.           425,984 Boo.Lang.Parser.dll
10/08/2009  03:48 p.m.            28,672 Boo.Lang.PatternMatching.dll
10/08/2009  04:01 p.m.            81,920 Boo.Lang.Useful.dll
10/08/2009  04:01 p.m.            32,768 Boo.Microsoft.Build.Tasks.dll
10/08/2009  04:01 p.m.            28,672 Boo.NAnt.Tasks.dll
10/08/2009  04:07 p.m.               393 BusOnTransactionalQueue.config
10/08/2009  04:07 p.m.               405 BusWithLogging.config
10/08/2009  03:48 p.m.            45,056 Cassini.dll
12/08/2009  09:43 p.m.           249,856 Castle.ActiveRecord.dll
12/08/2009  09:43 p.m.             6,656 Castle.ActiveRecord.Linq.dll
12/08/2009  09:43 p.m.            17,920 Castle.ActiveRecord.Linq.pdb
12/08/2009  09:43 p.m.             4,736 Castle.ActiveRecord.Linq.xml
12/08/2009  09:43 p.m.           960,000 Castle.ActiveRecord.pdb
10/08/2009  04:02 p.m.           543,085 Castle.ActiveRecord.XML
12/08/2009  09:42 p.m.            49,152 Castle.Components.Binder.dll
12/08/2009  09:42 p.m.           138,752 Castle.Components.Binder.pdb
12/08/2009  09:42 p.m.            17,275 Castle.Components.Binder.xml
                 ... And the list goes ...





353 File(s) 67,002,734 bytes 2 Dir(s) 578,875,887,616 bytes free

Not bad for what was effectively just a single command line.

Where to from here

I strongly suggest giving Horn a go – not just because it’s useful, but I think that it fills a real hole in the .Net developer open source space, removing one of the barriers to entry – making it easier for people to develop applications against the trunk, or a specific version, of many popular open source projects, will definitely drive up adoption of these projects.

It’s worth noting that currently “Horn” is considered a “developer-only” release at the moment, though I think it’s current state is useful enough to warrant giving it a try, and providing feedback to the Horn dev team etc. so umm… Check it out, if you haven’t already.  I think you’ll be pleasantly surprised.

posted @ Wednesday, August 12, 2009 11:31:53 PM (New Zealand Standard Time, UTC+12:00)    Comments [3] | |
# Saturday, September 06, 2008
As a brief follow up to my last post here I thought I'd quickly post about something I've been doing lately with my own windsor configurations, which is pretty minor - but saves me a little grief when it comes to refactoring etc.

Basically I have this extension method:


public static ComponentRegistration<S> RegisterTransient<S>(this IWindsorContainer container, ComponentRegistration<S> registration)

{

  container.Register(registration.LifeStyle.Transient);

  return registration;

}



Which then lets me do this:


var serviceA = container.RegisterTransient(Component.For<IStaffRepository>()

  .ImplementedBy<StaffRepositoryA>());


var serviceB = container.RegisterTransient(Component.For<IStaffRepository>()

  .ImplementedBy<StaffRepositoryB>());

 

container.Register(Component.For<IStaffService>().Named("service.staff").ImplementedBy<StaffService>()

  .ServiceOverrides(ServiceOverride.ForKey("Repositories").Eq(serviceB.Name, serviceA.Name)));

 

var staffService = (StaffService)container.Resolve<IStaffService>();

 

Assert.IsType<StaffRepositoryB>(staffService.Repositories[0]);

Assert.IsType<StaffRepositoryA>(staffService.Repositories[1]);



notice the lack of strings when registering service overrides... it's a minor thing, but I find it quite handy... plus it generally makes it easier to identify the lifestyle of the components being registered because it's a little more in your face, i.e. your making an explicit decision... though anywhere that lifestyle poses a risk you should obviously be writing some unit tests to verify your getting the expected behavior when resolving that service anyway.

Also, while looking at ComponentRegistration<S> -the other nice thing about the fluent component registration is it works quite well for add-ons that introduce their own services which aren't loaded into a seperate app domain or child kernel ...

Just give the add-in an installation "helper" which only exposes a method taking a ComponentRegistration<S> for registering the component... you can then defer when those services are actually registered in the kernel, and can use the names of the components or other info to unregister them if the add-in is turned off (obviously this is a rainy day scenario and there are problems with this approach, but so far I've found it to work quite well).

posted @ Saturday, September 06, 2008 9:13:02 AM (New Zealand Standard Time, UTC+12:00)    Comments [0] | |
If you recall when configuring the container via xml you can do a service override like so:

<configuration>

 

    <components>

        <component id="smtp.sender"

            service="Namespace.IEmailSender, AssemblyName"

            type="Namespace.SmtpMailSender, AssemblyName" />

 

        <component id="sendmail.sender"

            service="Namespace.IEmailSender, AssemblyName"

            type="Namespace.SendMailEmailSender, AssemblyName" />

 

        <component id="newsletter"

            type="Namespace.NewsLetterSenderService, AssemblyName">

 

            <parameters>

                <sender>${smtp.sender}</sender>

            </parameters>

 

        </components>

 

    </components>

 

</configuration>


Check out the documentation on the castle site for some more details.

I recently got an email question around how to do this with the fluent interface - unfortunately with the XML, Binsor and Fluent interfaces all being used for registering and configuring the MicroKernel/Windsor Container the documentation is a little patchy across all three (with XML of course having the best coverage) - so here's an example of service override for the fluent interface.

First off the various services we'll be wiring up in this example.

public interface IStaffService

{

}

 

public class StaffService : IStaffService

{

  public IStaffRepository Repository { get; set; }

}

 

public interface IStaffRepository

{

}

 

public class StaffRepositoryA : IStaffRepository

{

}

 

public class StaffRepositoryB : IStaffRepository

{

}


And now the actual tests..

public class ServiceOverrideTests

{

  private WindsorContainer container;

 

  public ServiceOverrideTests()

  {

    container = new WindsorContainer();     

    container.Register(Component.For<IStaffRepository>().Named("repository.staff.a").ImplementedBy<StaffRepositoryA>().LifeStyle.Transient);

    container.Register(Component.For<IStaffRepository>().Named("repository.staff.b").ImplementedBy<StaffRepositoryB>().LifeStyle.Transient);

  }

 

  [Fact]

  public void ByDefaultStaffServiceWiredUpToFirstServiceRegistered()

  {

    container.Register(Component.For<IStaffService>().Named("service.staff").ImplementedBy<StaffService>().LifeStyle.Transient);

 

    var staffService = (StaffService)container.Resolve<IStaffService>();

 

    Assert.IsType<StaffRepositoryA>(staffService.Repository);     

  }   

 

  [Fact]

  public void WithServiceOverrideCanPickImplmentationByKey()

  {

    container.Register(Component.For<IStaffService>().Named("service.staff").ImplementedBy<StaffService>()

                        .ServiceOverrides(ServiceOverride.ForKey("Repository").Eq("repository.staff.b")).LifeStyle.Transient);

 

    var staffService = (StaffService)container.Resolve<IStaffService>();

 

    Assert.IsType<StaffRepositoryB>(staffService.Repository); 

  }

}


With .ServiceOverrides(ServiceOverride.ForKey("Repository").Eq("repository.staff.b")) being the code we're interested in... obviously if it was a constructor override we'd be using the name of the parameter in the constructor.

The Eq method can also take of an array of strings... which, you guessed it, means we can handle arrays of services as well ... which can be quite handy if order is important to some kind of service you're building where there are multiple contributors or some form of pipeline, lets take a look at that:

public class StaffService : IStaffService

{

  public IStaffRepository[] Repositories { get; set; } // <- is now an array of staff repository...

}


And the associated test - notice we just pass in a list of the service names...

[Fact]

public void WithServiceOverrideCanPickImplmentationByKey()

{

  container.Register(Component.For<IStaffService>().Named("service.staff").ImplementedBy<StaffService>()

                      .ServiceOverrides(ServiceOverride.ForKey("Repositories").Eq("repository.staff.b", "repository.staff.a")).LifeStyle.Transient);

 

  var staffService = (StaffService)container.Resolve<IStaffService>();

 

  Assert.IsType<StaffRepositoryB>(staffService.Repositories[0]);

  Assert.IsType<StaffRepositoryA>(staffService.Repositories[1]);

}


Hopefully this proves useful to Jason (who sent me the email) and anyone else who's getting started with windsor and strugling a little to setup their container.
posted @ Saturday, September 06, 2008 8:29:15 AM (New Zealand Standard Time, UTC+12:00)    Comments [4] | |
# Tuesday, September 02, 2008
So I received a question recently via email from someone following the container tutorials, which read like so:

Read through you tutorials and great work!

Have a question for you though, that I can't seem to find an answer in google. On decorators. How do you provide state dependencies that are unknown at configuration time?

So I ask for an IRepository and I have configuration setup to wrap it in a IValidator and maybe an ISecurity. However, ISecurity has a dependency on a runtime determined role (say from multiple sources, possibly including a state value on IWidget) and the user id (for argument sake isn't available on the context).

I want to call T Get() on IRepository. How do you get it all setup?

Many Thanks!

As I see it there were two distinct questions asked:
  • How to wire up generic decorator chains (though I suspect they already know how to do that).
  • How to pass in parameters/dependencies at run time.
So Let's look at doing these two things, I'm going to steer clear of xml configuration because that's so 2 years ago ;o)

First off let's create the repository interface:

public interface IRepository<T>

    where T : class, new()

{

    T Get(int id);

}


Then the root implementation (we can't keep chaining forever, at some point we have to hit an implementation which can actually return the results we want).

public class StubRepository<T> : IRepository<T>

    where T : class, new()

{

    public T Get(int id)

    {

        return new T();

    }

}


And finally a decorator for "security"...

public class SecurityDecorator<T> : IRepository<T>

    where T : class, new()

{

    private readonly IRepository<T> _inner;

 

    public SecurityDecorator(IRepository<T> inner)

    {

        _inner = inner;

    }

 

    public T Get(int id)

    {

        return _inner.Get(id);

    }

}


better have a widget too... for good measure:

public class Widget

{

}


At this point we can write a test - I'm an xUnit fanboy these days (typing less == good) so let's take a look:

public class ContainerTests

{

    private readonly IWindsorContainer container;

 

    public ContainerTests()

    {

        container = new WindsorContainer();

        container.Register(Component.For(typeof (IRepository<>)).ImplementedBy(typeof (SecurityDecorator<>)));

        container.Register(Component.For(typeof (IRepository<>)).ImplementedBy(typeof (StubRepository<>)));

    }

 

    [Fact]

    public void GetRepository_ForWidget_ReturnsSecurityDecoratorOfTypeWidget()

    {

        var widgetRepository = container.Resolve<IRepository<Widget>>();

        Assert.True(widgetRepository is SecurityDecorator<Widget>);

    }

}


Notice we register the components in top to bottom order i.e. decorators first, followed by the underlying implementation, for something as simple as this you don't really need to use the fluent interface for registering components - but I find it's good to be consistent.

Now, the second question is about injecting "context" - this is really just another way of saying "some of my dependencies can't be known until just before I attempt to resolve the service" ... no problem... so let's make some modifications:

First off I'm going to make a user...

public interface IUser

{

}


Next thing I'm going to do is add a User property to my security context (ugh, this seems like a better job for some kind of "ICurrentUserHolder" service, but that's beside the point).

public class SecurityDecorator<T> : IRepository<T>

    where T : class, new()

{

    private readonly IRepository<T> _inner;

 

    public SecurityDecorator(IRepository<T> inner)

    {

        _inner = inner;

    }

 

    public T Get(int id)

    {

        return _inner.Get(id);

    }

 

    public IUser User { get; set; } // <-- the current user

}


Now let's add another test to ensure everything is being injected properly...

public class ContainerTests

{

    private readonly IWindsorContainer container;

    private readonly IUser user = MockRepository.GenerateStub<IUser>();

 

    public ContainerTests()

    {

        container = new WindsorContainer();

        container.Register(Component.For(typeof (IRepository<>)).ImplementedBy(typeof (SecurityDecorator<>)));

        container.Register(Component.For(typeof (IRepository<>)).ImplementedBy(typeof (StubRepository<>)));           

    }

 

    [Fact]

    public void GetRepository_ForWidget_ReturnsSecurityDecoratorOfTypeWidget()

    {

        var widgetRepository = container.Resolve<IRepository<Widget>>();

        Assert.True(widgetRepository is SecurityDecorator<Widget>);

    }

 

    [Fact]

    public void GetRepository_ForWidget_WhenSupplyingUserInjectsUserIntoSecurityRepository()

    {

        var securityDecoratorForWidget = (SecurityDecorator<Widget>) container.Resolve<IRepository<Widget>>(new {User = user});

        Assert.Same(user, securityDecoratorForWidget.User);

    }

}


Notice the additional argument of an anonymous class being passed to Resolve, this allows us to provide additional parameter dependencies (in this case a stub user is being supplied).

Finally what about passing in some roles... this is much of the same, but I'll include it for completeness... so we add a role interface:

public interface IRole

{

    bool IsMember(IUser user);

}


Then we'll add a collection of roles to the decorator and provide a rather primitive check against the roles when attempting to get a widget instance:

    public class SecurityDecorator<T> : IRepository<T>

        where T : class, new()

    {

        private readonly IRepository<T> _inner;

 

        public SecurityDecorator(IRepository<T> inner)

        {

            _inner = inner;

        }

 

        public T Get(int id)

        {

            CheckPermission();

            return _inner.Get(id);

        }

 

        public IUser User { get; set; }

 

        public IList<IRole> Roles { get; set; } // <-- the roles to check

 

        private void CheckPermission()

        {

            if (User == null || Roles == null) return;

 

            if (Roles.Any(role => !role.IsMember(User)))

            {

                throw new Exception("You do not have permission");

            }

        }

    }


And finally we update our test with checks for both passing and failing on the permissions check.

public class ContainerTests

{

    private readonly IWindsorContainer container;

    private readonly IUser user = MockRepository.GenerateStub<IUser>();

    private readonly IRole failingRole = MockRepository.GenerateStub<IRole>();

    private readonly IRole passingRole = MockRepository.GenerateStub<IRole>();

 

    public ContainerTests()

    {

        container = new WindsorContainer();

        container.Register(Component.For(typeof (IRepository<>)).ImplementedBy(typeof (SecurityDecorator<>)));

        container.Register(Component.For(typeof (IRepository<>)).ImplementedBy(typeof (StubRepository<>)));

        passingRole.Stub(stub => stub.IsMember(user)).Return(true);

    }

 

    [Fact]

    public void GetRepository_ForWidget_ReturnsSecurityDecoratorOfTypeWidget()

    {

        var widgetRepository = container.Resolve<IRepository<Widget>>();

        Assert.True(widgetRepository is SecurityDecorator<Widget>);

    }

 

    [Fact]

    public void GetRepository_ForWidget_WhenSupplyingUserInjectsUserIntoSecurityRepository()

    {

        var securityDecoratorForWidget = (SecurityDecorator<Widget>) container.Resolve<IRepository<Widget>>(new {User = user});

        Assert.Same(user, securityDecoratorForWidget.User);

    }

 

    [Fact]

    public void Get_ForWidgetWhenUserMatchesAllRoles_ReturnsWidget()

    {

        var securityDecoratorForWidget =

            (SecurityDecorator<Widget>) container.Resolve<IRepository<Widget>>(new {User = user, Roles = new List<IRole> {passingRole}});

         Assert.NotNull(securityDecoratorForWidget.Get(1));

    }

 

    [Fact]

    public void Get_ForWidgetWhenUserDoesNotMatchAllRoles_ThrowsException()

    {

        var securityDecoratorForWidget =

            (SecurityDecorator<Widget>) container.Resolve<IRepository<Widget>>(new {User = user, Roles = new List<IRole> {passingRole, failingRole}});

         var exception = Assert.Throws<Exception>(() => securityDecoratorForWidget.Get(1));

        Assert.Equal("You do not have permission", exception.Message);

    }

}


And that's it... could not be simpler.


posted @ Tuesday, September 02, 2008 5:11:06 PM (New Zealand Standard Time, UTC+12:00)    Comments [0] | |
# Friday, August 15, 2008
Yesterday afternoon I presented a quick 20 minute presentation to the Enterprise Architect user group - it was an interesting opportunity to talk with both an Enterprise Architect lead developer and analysts/BA's etc. who are using Enterprise Architect on a daily basis - there's nothing quite like doing something and then even more so presenting on what you've done to really firm up some conclusions / ideas around it (and as is often the case with me, spark 20 ideas for new products I could build to make it better/smarter).

For anyone who's interested here's the slide deck I presented - and also some links to things that were discussed:
Thanks to catch for hosting the group and providing the video conferencing facilities to link Auckland / Wellington (small tip, if you are presenting to two groups be sure to sit at the end of the table looking towards the camera, or your spend your whole time ping-ponging your head towards one group and the other ;) - and also thanks to everyone who came along and listened.

Also of interest was the discussion after the presentation around providing a number of example/sample MDA transformations through Sparx Systems New Zealand site - which should mean that before the end of the year you will be seeing both guidance and examples on developing MDA transformations targeting NHibernate, NHibernate search, ActiveRecord, Monorail and RhinoSecurity starting to emerge (what I tend to loosely call the "Castle stack" for want of a better term.) - which I'll post about it as it starts to happen.

posted @ Friday, August 15, 2008 2:19:21 PM (New Zealand Standard Time, UTC+12:00)    Comments [0] | |
# Monday, June 30, 2008
Jonathon Rossi over in Brisbane has been hard at work on the CVSI project (Castle Visual Studio Integration) and has released version 0.3 which now supports VS 2008 - for those not in the know CVSI provides nvelocity intellisense when writing views for monorail.

I did some testing of some earlier releases last week and it's looking good, hilights include:
  • New installer which supports 2005 and 2008.
  • Basic XHTML intelisense.
It also includes some fixes which means the intelisense now works when the templates are not in a web application project (useful for those of us writing applications where we have pluggable modules) and fixes for multi-level inheritence, so helpers and view components with multiple levels of base class i.e. FormHelper (which now inherits from AbstractFormRelatedHelper) will be included in the list of classes, something which bugged me with earlier releases on 2005.

Great work Jono!

posted @ Monday, June 30, 2008 8:31:14 PM (New Zealand Standard Time, UTC+12:00)    Comments [0] | |
# Thursday, June 19, 2008
If you recall many moons ago I posted a series of articles on the Castle Project's IOC Container "Windsor" teaching the fundamentals of IoC with a practical bent - lots of people liked them, and I still get feedback every now and then from people starting to use windsor and finding them useful.

At any rate Michael McGuire was once such person who read those tutorials a year or so ago and has now started a series of his own - mirroring my castle container tutorials but with the P&P Unity container instead - you can find it here.

As someone who has not given Unity much more then a brief skim it's a nice way to quickly get up to speed on some of the key differences.

So far after reading a couple of articles I've learnt.
  • You need to implement your own type converters for things like arrays or dictionaries in configuration.
  • Configuration syntax is not particularly human-friendly, obviously designed for management via a tool  - requiring the entry of full types all over the spot like "Microsoft.Practices.Unity.Configuration.TypeInjectionElement, Microsoft.Practices.Unity.Configuration" - just to register a component!
  • Default lifestyle is transient... hmmm.. personally I think singleton is more-often the norm for me when writing applications, but it really depends on how the container is being used/abused I guess.
  • Support for multiple configurations looks a little more baked in - but this is trivial stuff to implement in most containers.
I'll be interested to see how decorator chains etc. are implemented in Unity.

Good work Michael.

.Net | castle | Unity | windsor
posted @ Thursday, June 19, 2008 12:45:04 PM (New Zealand Standard Time, UTC+12:00)    Comments [2] | |
# Sunday, December 02, 2007
So a quick observation on the alt.net conference list:

"You’ll be happy to know then that in the new WPF Composite work we are doing, the DI/IOC mechanism will be decoupled and pluggable. Actually the next version of Entlib will be the same. There’s a new Dependency Injection block that will allow you to plug-in the container of your choice."

Which was posted on the alt.net conference yahoo list by by Glen Block from Microsoft.

I think this is very good news, at least for the WPF composite work they're doing - it might make it a great deal more appealing to me then the CAB was (I was never a big fan of the CAB because it didn't integrate well with the other stacks of technologies that made me productive).

I'm fairly ambivalent about the Enterprise Libraries upcoming pluggable IoC support however - surely the overlap between it and the facilities and services already provided by the IoC container you'd be plugging into would be great ... and IoC is only part of that story... for a number of common services (i.e. logging, transactions etc.) you're going to have create appropriate wrappers and sandwich things into the containers "abstracted" view of the world, or face tightly coupling your application to the Enterprise Library, I'm not sure there is much of a value proposition there... though I'm open to being educated if any P&P Microsoft people happen to read this.

Interestingly enough has picked up on this slip from Glen and noted that it also implies Microsoft are writing yet another IoC container that will probably ship with EntLib & the WPF composite work (in whatever shape it eventually takes) and they ask the question "why oh why!" .

Personally I think it makes good sense to provide an out of the box IoC container, with it the product is far more accessible to new developers and people reviewing the technology - especially when you consider that:
  • If support was added into say the Castle Windsor container, it wouldn't see an official release until RC4 was made public - and until then would be in a state of flux as part of the castle trunk.
  • People would expect Microsoft to "suggest" an OSS container that works best with their offering - and playing favorites with the .Net OSS community could only do harm to the ecology I feel.
  • Microsoft retain consistency with their existing approach of providing an entire stack of technologies for you to get the job done, if that's what your like/want or are told you want. 
  • They can provide a set of consistent tutorials and training materials for developers to "get up to speed" with for the product, without having to provide umpteen alternative examples for different containers, or explain why the container terminology is slightly different to the product terminology.
So in short, I think it's a positive sign, not a negative one, even if another container is introduced into the mix - I'll be interested in seeing just how they do it (both the container, and the extension points to allow for plugging in a different container)... Though it could just be a hack using IServiceProvider, I wonder if perhaps they may need to go a bit further, so they can register services into the plugged in container with the appropriate lifestyle and configuration etc.

Edit: I just noticed Ayende posted about this as well...  he seems pretty well aligned with the "why oh why" viewpoint, perhaps I'm missing something - but I just don't see it being all that practical in some scenarios to provide a product that wont work without the developer going through a separate selection process to pick an IoC container, if they don't already use one from the OSS community.
posted @ Sunday, December 02, 2007 12:08:07 PM (New Zealand Daylight Time, UTC+13:00)    Comments [1] | |
# Tuesday, October 30, 2007
Just a quick note that I've put together a small guide on working with the Castle / Nhibernate / RhinoTools trunk here on my wiki, which goes well as a companion to this article on working with the Castle trunk which can be found on using.castleproject.org.

Hopefully it proves useful to someone other that myself.

posted @ Tuesday, October 30, 2007 9:30:36 PM (New Zealand Daylight Time, UTC+13:00)    Comments [7] | |
# Friday, September 21, 2007
Quite a good turnout, with well over a table full (I didn’t take an official count, but I’m guessing around 12 or more) including Alex James and Keith (who we hadn’t seen for a while) and two newcomers from Olympic Software, which was great - we always like to see fresh faces and ideas.

I talked very briefly about Castle Project RC3 – I suggested it was a week or two away from getting out the door, but in fact - It’s out as of about an hour ago! (11:30am) - the website and documentation is still in the process of being updated, but the installer and binaries/source are all here.

I was going to run through some of the changes I like in RC3 – but the conversation got steered away before I got warmed up - but it's well worth checking out, if you haven't been keeping an eye on the trunk and the changes that have been going in.

At any rate – this is the culmination of a huge amount of work from many of the Castle contributors, I think it even has a 2 line patch of my own in there somewhere :P ... great work guys!

PLINQ – talked about PLINQ getting closer, and the fact that parallelization is a very hot topic of late, with a few noting that the last MSDN mag was almost entirely focused on this subject.

On a tangent, Erlang cropped, not too many of us have had exposure to the language details, but Keith had done some spelunking and gave us a quick rundown of how it all hangs together, definitely something to keep an eye on - Andrew Peter's even called it his "Language of the year".

I brought up the MediaDefender debacle that’s been unravelling over the last week or so since their huge mail leak.  Not only are the inner workings of this organisation pretty unprofessional and certainly bordering on unethical for a corporation, but it highlights the risk most organisations run – the source of the leak being one employee who automatically forwarded all his work email to a gmail account, who then used the exact same credentials elsewhere.

Keith gave us some insight into LUA, including why it doesn’t make an attractive language to port to .Net, and why it’s so much easier to embed in a C++ based project as opposed to something like Ruby, which just seem to be designed for that purpose, especially with it's "out of the box" set of global variables.

I asked the question “What web load testing apps do you use” – and the answer was generally, we don’t!... I’ve been reviewing WebLOAD – which looks quite good, especially because the load machines can be deployed on a non Microsoft machine, such as Linux, making it easier to span a number of load machines out on something like Amazons elastic cloud (EC2), or low-cost machines without the hassle of O/S licensing.

We then moved onto talking about high-scale load testing, i.e. simulating a million simultaneous requests – somebody suggested that maybe you could hire whoever’s pulling the strings on the Storm BotNet – though I’m not sure they’re into self-promotion ;o)

We talked about social networking applications, and leveraging social networking platforms with API’s such as face book, this has been a popular topic over the last couple of months, including:
  • Finding the killer app(s) that could leverage an API like face book’s, and making money out of it.
  • Bad habits encouraged by these platforms, such as requesting your email account username and password to “email your friends”.
Alex James brought up the great series of posts that Rowan Simpson has been making lately – not everyone knew who Rowan was... so hopefully they should know now ;o) the posts walk through, the Trade me manifesto, and then drills into:
Over lunch we talked about many things, mostly non-IT related, but some things that did come up, including that the Mac OS isn’t going to have a NZ Daylight savings time update before Daylight savings actually kicks in, though it's not really a problem.

Some things that got mentioned which I didn’t quite catch the details of:

  • Metabase (I’m not sure I got the name right – couldn’t find a link, but apparently it’s a game / game development platform, in alpha development at the moment, where all game assets have an associated URL, and maybe an RSS Feed??) – Alex James suggested it might be interesting to combine something like that with a web based data storage platform, such as freebase, developed by Metaweb Tech.
  • Jason K (Knowles?) - who apparently supports the Idea of every user having there own domain, to cement their various web identities together, and where all their data is held by them in one place. – can anyone throw me the correct name and url?



posted @ Friday, September 21, 2007 12:22:34 PM (New Zealand Standard Time, UTC+12:00)    Comments [0] | |
# Thursday, July 26, 2007
About to run off to a meeting... so I'll make this quick.

Just read an interesting post by Donald Belcham on Refactoring Analysis with the help of nDepend... he's gone through the process of moving from .Net 1.1 to 2.0, then introducing interface based code, breaking classes apart to ensure they're enforcing the principle of single responsibility, moving to injecting dependencies, rolling his own primitive Inversion of Control container and finally employing the Castle Project's windsor container instead.

It pays to know a little bit about nDepend of course to understand the Abstractness vs Relational Cohesion figures... either take a look at the nDepend site, or maybe have a listen to the .Net Rocks podcast earlier this year which covered the same topic.

I'm not sure the figures actually answer questions so much as they ask them ... but it's interesting to see how much impact his first two rounds of refactoring had on the results.

I wonder how the figures would've come out had he executed his refactoring in a different order...  maybe DI first, then breaking the classes up based on responsibility, IoC and then finally introducing interfaces... hmmm

posted @ Thursday, July 26, 2007 1:57:28 PM (New Zealand Standard Time, UTC+12:00)    Comments [0] | |
# Saturday, July 14, 2007
Wasted 5 minutes figuring out what was going wrong, maybe this will save someone else the effort!

When using RhinoCommons and CastleProject both from trunk there's a version conflict with NHibernate.

RhinoCommons has NHibernate Version 2.0.0.1001 (Including support for things like Multi-criteria) ... and then the Castle Project is using NHibernate Version (1.2.0.4000) - this took me a little bit by surprise when I discovered that a monorail project I had was failing when attempting to databind properly when using the ARSmartDispatcherController... because I wasn't checking the binding errors collection, this was just failing silently... so a save would just load/save the existing record, without any binding.

Quick fix is just to use a assembly binding redirect in the web.config:

<runtime>

    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">

        <publisherPolicy apply="no"/>

        <dependentAssembly>

            <assemblyIdentity name="NHibernate" publicKeyToken="aa95f207798dfdb4" culture="neutral" />

            <bindingRedirect oldVersion="1.2.0.4000" newVersion="2.0.0.1001"/>

        </dependentAssembly>

    </assemblyBinding>

</runtime>




posted @ Saturday, July 14, 2007 1:13:35 PM (New Zealand Standard Time, UTC+12:00)    Comments [4] | |
# Wednesday, May 30, 2007
I've been getting a few questions about different aspects of the container tutorials series I posted a while back - while the series is not finished, neither is it forgotten, I've collated information regarding the series into a topic on my wiki and I'll keep this up to date until I've finished the series off.

I also notice Sam Gentile has posted that he's taking the plunge into learning about castle's Windsor container... good to hear :)


castle | IoC | wiki
posted @ Wednesday, May 30, 2007 5:30:43 PM (New Zealand Standard Time, UTC+12:00)    Comments [0] | |
# Sunday, April 29, 2007
14_startable_facility.png

So this time we're going to have a look at the startable facility (you can find more info on it here in the wiki) - the concept of the startable facility is to ensure that components are started as soon as possible, which translates to as soon as all dependencies are available. 

Effectively what happens is you create a component, and implement a special interface called IStartable, which looks like this and is found in the Castle.Core assembly.

/// <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();

}


And then the startable facility detects any components registered in the container which implement the IStartable interface and determines if they have any dependencies which still need to be satisfied, if not, then the container will Resolve the component, and start it immediately (by invoking the IStartable.Start method on it) otherwise it's added to a list of services awaiting startup.

From then on, as components are registered in the container the startable facility will check the list of services awating startup, to see if any of them have all their dependencies available now, if so it will then Resolve the service and again invoke IStartable.Start on it.

Now at this point it's worth noting that Start is not executed asynchronously - if you block within the Start method then your container will halt loading the configuration etc. till it completes... be careful not to slow down your container startup too much with slow blocking operations with the Start() method.

So let's get into some code... first off I'm going to create a simple http listening service which is capable of serving up a single file... exciting stuff!

Here's the code:

public class LameHttpFileServer : IStartable

{

    private string _path;

    private HttpListener _listener;

    private Thread _listenerThread;

    private ILogger _logger;

 

    public LameHttpFileServer(string prefix, string path)

    {

        _path = path;

        _listener = new HttpListener();

        _listener.Prefixes.Add(prefix);

    }

 

    public ILogger Logger

    {

        get

        {

            if (_logger == null) _logger = NullLogger.Instance;

            return _logger;

        }

        set { _logger = value; }

    }

 

    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("Stopped LameWebService.");

    }

 

    private void RequestWorker()

    {

        while (true)

        {

            HttpListenerContext context = null;

 

            try

            {

                context = _listener.GetContext();

            }

            catch (ObjectDisposedException)

            {

                return;

            }

 

            ServeContent(context.Response, _path);

        }

    }

 

    private void ServeContent(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();

    }

}


Now, this class doesn't have any constructor dependencies (beyond a little configuration) but we do have a Setter dependency on an ILogger service - ILogger is actually a generic abstract of a logger for a logging framework (a logger being a named/scoped class supporting a number of generic message writing methods) out of the box Castle provides support for both nlog and log4net, however it also contains some lightweight loggers, such as a console logger, which means you can avoid having to write any logging configuration files... so we're going to use that this time... because the loggers are assigned by the container, there's not need to actually reference the type the logger is logging "for", because the container knows that implicitly.

Now let's have a look at the container configuration:

<configuration>

 

  <configSections>

    <section name="castle"

        type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor" />

  </configSections>

 

  <castle>

    <facilities>

      <facility id="startable.facility"

        type="Castle.Facilities.Startable.StartableFacility, Castle.MicroKernel" />

 

      <facility id="logging.facility"

        type="Castle.Facilities.Logging.LoggingFacility, Castle.Facilities.Logging"

        loggingApi="console" />                         

 

  </facilities>

    <components>

 

      <component id="serves->lame.html"

                type="IoC.Tutorials.Part14.LameHttpFileServer, IoC.Tutorials.Part14">

        <parameters>

          <prefix>http://*:8089/</prefix>

          <path>lame.html</path>

        </parameters>

      </component>

 

    </components>

  </castle>

 

</configuration>


As you can see we have declared two facilities, one for handling the auto-wiring of Loggers into any components with ILogger constructor parameters or setter dependencies, and secondly the startable facility, which will take care of automatically starting our LameHttpFileServer for us.

Now, notice we're referencing a file called lame.html - heres what that looks like:

<html>

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


Now done to business, let's look at the program that's using this server...

private static void Main(string[] args)

{

    WindsorContainer container = new WindsorContainer(new XmlInterpreter());

 

    GetPage();

 

    container.Dispose();

 

    GetPage();

 

    Console.Read();

}

 

private static void GetPage()

{           

    Console.WriteLine("\r\nClient: requesting http://localhost:8089/ ...");

    try

    {

        WebClient client = new WebClient();

        string content = client.DownloadString("http://localhost:8089/");

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

    }

    catch (WebException ex)

    {

        Console.WriteLine("Client: Exception occured, message: {0}", ex.Message);

    }

}


As you can see what we're doing is:

  1. Constructing the container using the configuration.
  2. Calling the GetPage method, which will attempt to download the lame.html file from our server (which the container should have started automatically for us)
  3. Disposing of the container (any guesses what that will do?)
  4. And finally calling the GetPage method again, to see if our server is still running.
So, running the program gives us these results:

[Debug] 'IoC.Tutorials.Part14.LameHttpFileServer' Starting LameWebService...
[Info] 'IoC.Tutorials.Part14.LameHttpFileServer' LameWebService Started.

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

 <html>
    <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] 'IoC.Tutorials.Part14.LameHttpFileServer' Stopping LameWebService...
[Info] 'IoC.Tutorials.Part14.LameHttpFileServer' Stopped LameWebService.

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

As you can see before we disposed of the container our request for the file worked just fine, but after the container had been disposed, it appears the file service has been stopped, and so our client was unable to connect... what caused this?

Well the way the startable service is implemented, it actually applies a couple of lifecycle concerns - a concern is effectively a bit of code that executes when what it's concerned in occurs, in these case the startable facility adds two concerns to a startable component's model.

The first "concern" is a commission concern, which invokes the Start method upon the component entering the commission step of it's lifecycle, which is immediately after the component instance has been constructed and all it's dependencies and configuration injected. 

The second concern is a "decommission" concern, which occurs upon the component is being decommissioned (ie. disposed of, released or purged from the container) this happens to all components the container is holding onto when it is disposed, or when an individual component is released - however in the case of components with a singleton lifestyle, you can't actually release the component prior to disposing of the container (because that would violate the lifestyle) ... so doing something like this:

LameHttpFileServer server = container.Resolve<LameHttpFileServer>();

container.Release(server);


In place of disposing the container won't stop the service if it's a singleton....

One last though - what would happen if we changed our components lifestyle to [Transient] instead of the default of singleton, let's create a simple class for testing this idea:

[Transient]

public class StartableExperiment : IStartable

{

    private static int _count;

    private int _number;

 

    public StartableExperiment()

    {

        _number = ++_count;

    }

 

    public void Start()

    {

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

    }

 

    public void Stop()

    {

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

    }

}


Now let's write some code to test it... we'll just register the component in code, to avoid having to change our config...

Here's the program itself...

WindsorContainer container = new WindsorContainer(new XmlInterpreter());

 

container.AddComponent("exp", typeof(StartableExperiment));

 

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

container.Release(exp1);

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

container.Release(exp2);

 

container.Dispose();


And the results:

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


So what's happened is that immediately upon registration a component is created... and can't be disposed (because we can't get a hold of the instance to release it) until the container is disposed... but for the couple of calls to Resolve and Release you can see the StartableExperiment instances are started & stopped during commission & decommission steps in the components life cycle as expected.

So that brings this look at the startable facility to an end... next time we might have another quick look at life cycles to see how else we can use this concept when build components, and maybe after that we'll have a look at some of other lifestyles which are available "out of the box" and how to write our own.
posted @ Sunday, April 29, 2007 4:51:25 PM (New Zealand Standard Time, UTC+12:00)    Comments [3] | |
# Saturday, April 28, 2007
13_injecting_service_arrays.png
So this time we're going to look at injecting service arrays ... if you haven't read part 12, it might pay to have a look at that first - this part follows on from the examples presented there.

So this should be reasonably quick, we're just going to rework the Part 12 solution so we don't need decorators... why would we do this, well in this case I feel that rewiring decorators (ie. changing orders, or disabling one of the decorators temporarily) isn't completely intuitive, especially when you have a long chain, it's easy to make mistakes.

So what's the plan, well first off let's implement an abstract class for our calculators:

public abstract class AbstractCalculator

{

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

}


Now we can rework the existing decorators and default calculator to be implementations of the abstract caculator, so here goes:

First off the the logic in the DefaultCostCalculator will be moved into a class called TotalCalculator :

public class TotalCalculator : AbstractCalculator

{

    private decimal CalculateTotal(Order order)

    {

        decimal total = 0;

 

        foreach (OrderItem item in order.Items)

        {

            total += (item.Quantity*item.CostPerItem);

        }

 

        return total;

    }

 

    public override decimal Calculate(decimal currentTotal, Order order)

    {

        return currentTotal + CalculateTotal(order);

    }

}


And then for the gst calculator, we do much the same thing:

public class GstCalculator : AbstractCalculator

{

    private decimal _gstRate = 1.125m;

 

    public decimal GstRate

    {

        get { return _gstRate; }

        set { _gstRate = value; }

    }

 

    private bool IsNewZealand(Order order)

    {

        return (order.CountryCode == "NZ");

    }

 

    public override decimal Calculate(decimal currentTotal, Order order)

    {

        if (IsNewZealand(order))

        {

            return (currentTotal*_gstRate);

        }

 

        return currentTotal;

    }

}


And finally the shipping calculator:

public class ShippingCalculator : AbstractCalculator

{

    private decimal _shippingCost = 5.0m;

    private decimal _fragileShippingPremium = 1.5m;

 

    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;

 

        foreach (OrderItem item in order.Items)

        {

            decimal itemShippingCost = ShippingCost*item.Quantity;

            if (item.IsFragile) itemShippingCost *= FragileShippingPremium;

            shippingTotal += itemShippingCost;

        }

 

        return shippingTotal;

    }

 

    public override decimal Calculate(decimal currentTotal, Order order)

    {

        return currentTotal + GetShippingTotal(order);

    }

}


Now, our original DefaultCostCalculator is reworked to use an array of AbstractCalculators to compute the total cost for an order:

public class DefaultCostCalculator : ICostCalculator

{

    private AbstractCalculator[] _calculators;

 

    public DefaultCostCalculator(AbstractCalculator[] calculators)

    {

        _calculators = calculators;

    }

 

    public decimal CalculateTotal(Order order)

    {

        decimal currentTotal = 0;

 

        foreach (AbstractCalculator calculator in _calculators)

        {

            currentTotal = calculator.Calculate(currentTotal, order);

        }

 

        return currentTotal;

    }

}


Notice it takes an array of AbstractCalculator's as a constructor dependency... just like we did for configuration parameters in the early parts of this container tutorial series, we can actually pass arrays of dependencies to a component as well, so last of all let's see the container configuration:

<configuration>

 

  <configSections>

    <section name="castle"

        type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor" />

  </configSections>

 

  <castle>

    <components>

 

      <component id="calc.gst"

                service="IoC.Tutorials.Part13.AbstractCalculator, IoC.Tutorials.Part13"

                type="IoC.Tutorials.Part13.GstCalculator, IoC.Tutorials.Part13">

        <parameters>

          <GstRate>1.20</GstRate>

          <!-- GST is now 20% -->

        </parameters>

      </component>

 

      <component id="calc.shipping"

          service="IoC.Tutorials.Part13.AbstractCalculator, IoC.Tutorials.Part13"

          type="IoC.Tutorials.Part13.ShippingCalculator, IoC.Tutorials.Part13">

        <parameters>

          <FragileShippingPremium>0.0</FragileShippingPremium>

          <!-- No fragile goods premium any more-->

        </parameters>

      </component>

 

      <component id="calc.total"

        service="IoC.Tutorials.Part13.AbstractCalculator, IoC.Tutorials.Part13"

          type="IoC.Tutorials.Part13.TotalCalculator, IoC.Tutorials.Part13" />

 

      <component id="costCalculator.default"

                service="IoC.Tutorials.Part13.ICostCalculator, IoC.Tutorials.Part13"

                type="IoC.Tutorials.Part13.DefaultCostCalculator, IoC.Tutorials.Part13">

        <parameters>

          <calculators>

            <array>

              <value>${calc.total}</value>

              <value>${calc.shipping}</value>

              <value>${calc.gst}</value>

            </array>

          </calculators>

        </parameters>

      </component>

 

    </components>

  </castle>

 

</configuration>


Notice the default caculator now takes our 3 calculators as members of an array, and if we want to change the order in which they are evaluated, it's trivial to just move them around within the <array /> node, or to comment certain ones out.

And just to demonstrate that nothing has changed, the code for the program in part 13 is identical to part 12:

private static void Main(string[] args)

{

    WindsorContainer container = new WindsorContainer(new XmlInterpreter());

 

    Order order1 = new Order();

    order1.CountryCode = "NZ";

    order1.Items.Add(new OrderItem("water", 10, 1.0m, false));

    order1.Items.Add(new OrderItem("glass", 5, 20.0m, true));

 

    Order order2 = new Order();

    order2.CountryCode = "US";

    order2.Items.Add(new OrderItem("sand", 50, 0.2m, false));

 

    ICostCalculator costCalculator = container.Resolve<ICostCalculator>();

    Console.WriteLine("Cost to deliver Order 1: {0}", costCalculator.CalculateTotal(order1));

    Console.WriteLine("Cost to deliver Order 2: {0}", costCalculator.CalculateTotal(order2));

 

    Console.Read();

}


And the results are the same too:

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


Beautiful :)

The next part will have a quick look at the "Startable" facility, enjoy.





posted @ Saturday, April 28, 2007 1:52:38 PM (New Zealand Standard Time, UTC+12:00)    Comments [0] | |
12_decorators.png
So... Decorators (for those who don't know, or don't remember) are a classic design pattern - have a look at the wikipedia entry if your curious on doing any background reading.

Up until now we've been creating abstractions and swapping implementations, but here we are going to chain implementations... so for this example we have an Order class which contains a bunch of order items, here's how that looks:

Order.cs

public class Order

{

    private string _countryCode;

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

 

    public List<OrderItem> Items

    {

        get { return _items; }

    }

 

    public string CountryCode

    {

        get { return _countryCode; }

        set { _countryCode = value; }

    }

}


OrderItem.cs

public class OrderItem

{

    private string _name;

    private bool _isFragile;

    private int _quantity;

    private decimal _costPerItem;

 

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

    {

        _name = name;

        _quantity = quantity;

        _costPerItem = costPerItem;

        _isFragile = isFragile;

    }

 

    public bool IsFragile

    {

        get { return _isFragile; }

        set { _isFragile = value; }

    }

 

    public int Quantity

    {

        get { return _quantity; }

        set { _quantity = value; }

    }

 

    public decimal CostPerItem

    {

        get { return _costPerItem; }

        set { _costPerItem = value; }

    }

 

    public string Name

    {

        get { return _name; }

        set { _name = value; }

    }

}


And now we have an interface that a class can implement to calculate the cost of an order:

public interface ICostCalculator

{

    decimal CalculateTotal(Order order);

}


And last of all we have an implementation of the cost calculator, which calculates the base cost of an order based on quantities and per-item costs:

public class DefaultCostCalculator : ICostCalculator

{

    public decimal CalculateTotal(Order order)

    {

        decimal total = 0;

 

        foreach (OrderItem item in order.Items)

        {

            total += (item.Quantity*item.CostPerItem);

        }

 

        return total;

    }

}


Pretty simple, so what about the program itself... well here it is, we just have 2 different orders we are calculating the total cost for:

internal class Program

{

    private static void Main(string[] args)

    {

        WindsorContainer container = new WindsorContainer(new XmlInterpreter());

 

        Order order1 = new Order();

        order1.CountryCode = "NZ";

        order1.Items.Add(new OrderItem("water", 10, 1.0m, false));

        order1.Items.Add(new OrderItem("glass", 5, 20.0m, true));

 

        Order order2 = new Order();

        order2.CountryCode = "US";

        order2.Items.Add(new OrderItem("sand", 50, 0.2m, false));

 

        ICostCalculator costCalculator = container.Resolve<ICostCalculator>();

        Console.WriteLine("Cost to deliver Order 1: {0}", costCalculator.CalculateTotal(order1));

        Console.WriteLine("Cost to deliver Order 2: {0}", costCalculator.CalculateTotal(order2));

 

        Console.Read();

    }

}


Our configuration (predictably) just had the default implementation of the cost calculator registered:

<component id="costCalculator.default"

          service="IoC.Tutorials.Part12.ICostCalculator, IoC.Tutorials.Part12"

          type="IoC.Tutorials.Part12.DefaultCostCalculator, IoC.Tutorials.Part12" />


Now lets see the output of running it:

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

So that seems OK... But I live in New Zealand, and in New Zealand we have GST (Goods and Services Tax) which means that I need to add another 12.5% to the total value of an order for NZ customers... so I could modify the default shipping calculator... but that's going to get ugly fast as more requirements come in (and more configuration needs to be exposed) - so instead I'll create a decorator for the cost calculator, just for doing GST:

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; }

    }

 

    private bool IsNewZealand(Order order)

    {

        return (order.CountryCode == "NZ");

    }

 

    public decimal CalculateTotal(Order order)

    {

        decimal innerTotal = _innerCalculator.CalculateTotal(order);

 

        if (IsNewZealand(order))

        {

            innerTotal = (innerTotal*_gstRate);

        }

 

        return innerTotal;

    }

}


Notice it's dependency on ICostCalculator, and that it actually invokes the inner calculator to get a total and then "decorates" the total (by adding the 12.5% when the country for the order is New Zealand).

Now we can actually wire this up in our container without changing any of our application code... let's look at that:

<configuration>

 

  <configSections>

    <section name="castle"

        type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor" />

  </configSections>

 

  <castle>

    <components>

 

      <component id="costCalculator.gstDecorator"

                service="IoC.Tutorials.Part12.ICostCalculator, IoC.Tutorials.Part12"

                type="IoC.Tutorials.Part12.GstCostCalcualtorDecoarator, IoC.Tutorials.Part12">

        <parameters>

          <innerCalculator>${costCalculator.default}</innerCalculator>

        </parameters>

      </component>

 

      <component id="costCalculator.default"

                service="IoC.Tutorials.Part12.ICostCalculator, IoC.Tutorials.Part12"

                type="IoC.Tutorials.Part12.DefaultCostCalculator, IoC.Tutorials.Part12" />

 

    </components>

  </castle>

 

</configuration>


Notice that the GSTdecorator is registered first (so it will be the default implementation of the ICostCalculator service) and it's inner calculator is wired to our default cost calculator... but proof is in the pudding, lets see what the results of running the program are now:

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


Great, so our New Zealand order is now ($110 * 1.125 = $123.75) - but our United states order is still at the original $10 dollars... but we forgot to calculate shipping... so let's add another decorator.

public class ShippingCostCalculatorDecorator : ICostCalculator

{

    private readonly ICostCalculator _innerCalculator;

    private decimal _shippingCost = 5.0m;

    private decimal _fragileShippingPremium = 1.5m;

 

    public ShippingCostCalculatorDecorator(ICostCalculator innerCalculator)

    {

        _innerCalculator = innerCalculator;

    }

 

    public decimal ShippingCost

    {

        get { return _shippingCost; }

        set { _shippingCost = value; }

    }

 

    public decimal FragileShippingPremium

    {

        get { return _fragileShippingPremium; }

        set { _fragileShippingPremium = value; }

    }

 

    public decimal CalculateTotal(Order order)

    {

        decimal innerTotal = _innerCalculator.CalculateTotal(order);

        return innerTotal + GetShippingTotal(order);

    }

 

    private decimal GetShippingTotal(Order order)

    {

        decimal shippingTotal = 0;

 

        foreach (OrderItem item in order.Items)

        {

            decimal itemShippingCost = ShippingCost*item.Quantity;

            if (item.IsFragile) itemShippingCost *= FragileShippingPremium;

            shippingTotal += itemShippingCost;

        }

 

        return shippingTotal;

    }

}


And of course, we need to wire that up as well:

<configuration>

 

  <configSections>

    <section name="castle"

        type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor" />

  </configSections>

 

  <castle>

    <components>

 

      <component id="costCalculator.shippingDecorator"

          service="IoC.Tutorials.Part12.ICostCalculator, IoC.Tutorials.Part12"

          type="IoC.Tutorials.Part12.ShippingCostCalculatorDecorator, IoC.Tutorials.Part12">

        <parameters>

          <innerCalculator>${costCalculator.gstDecorator}</innerCalculator>

        </parameters>

      </component>

 

      <component id="costCalculator.gstDecorator"

                service="IoC.Tutorials.Part12.ICostCalculator, IoC.Tutorials.Part12"

                type="IoC.Tutorials.Part12.GstCostCalcualtorDecoarator, IoC.Tutorials.Part12">

        <parameters>

          <innerCalculator>${costCalculator.default}</innerCalculator>

        </parameters>

      </component>

 

      <component id="costCalculator.default"

                service="IoC.Tutorials.Part12.ICostCalculator, IoC.Tutorials.Part12"

                type="IoC.Tutorials.Part12.DefaultCostCalculator, IoC.Tutorials.Part12" />

 

    </components>

  </castle>

 

</configuration>


Notice the chain, now we have Shipping -> GST -> Default Calculator .. so running the app again we can see the new totals:

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


Now there's a small problem here... we're calculating GST before shipping, this actually should be the other way round... think about what you would have to do to change this in a program normally - ugh!  But of course decorators and IoC containers are a great fit, we'll just change the order of decorators, and while we're at it, lets make GST 20% and no longer charge a premium for shipping fragile goods... easy!

<components>

 

  <component id="costCalculator.gstDecorator"

            service="IoC.Tutorials.Part12.ICostCalculator, IoC.Tutorials.Part12"

            type="IoC.Tutorials.Part12.GstCostCalcualtorDecoarator, IoC.Tutorials.Part12">

    <parameters>

      <innerCalculator>${costCalculator.shippingDecorator}</innerCalculator>

      <GstRate>1.20</GstRate> <!-- GST is now 20% -->

    </parameters>

  </component>

 

  <component id="costCalculator.shippingDecorator"

      service="IoC.Tutorials.Part12.ICostCalculator, IoC.Tutorials.Part12"

      type="IoC.Tutorials.Part12.ShippingCostCalculatorDecorator, IoC.Tutorials.Part12">

    <parameters>

      <innerCalculator>${costCalculator.default}</innerCalculator>         

      <FragileShippingPremium>0.0</FragileShippingPremium> <!-- No fragile goods premium any more-->

    </parameters>

  </component>

 

  <component id="costCalculator.default"

            service="IoC.Tutorials.Part12.ICostCalculator, IoC.Tutorials.Part12"

            type="IoC.Tutorials.Part12.DefaultCostCalculator, IoC.Tutorials.Part12" />

 

</components>


And for anyone sad enough to be checking the results with a calculator (or with the human equivalent ;o) we'll run the program one last time:

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


Now one thing to keep in mind is that so far we've been decorating return values... but you can also decorate methods with logic that occurs before invoking the inner service - a common example of this might be to validate something before it's committed to a repository (and perhaps throwing an exception if it's not OK) - and now suddenly you can turn validation on or off at the configuration level.

Next time we'll have a look at another way of writing this functionality without using decorators, stay tuned.
posted @ Saturday, April 28, 2007 12:27:50 PM (New Zealand Standard Time, UTC+12:00)    Comments [0] | |
# Wednesday, April 25, 2007
11_factories.png
So most all of us are familiar with factories, and at first glance it seems an IoC container removes the need for having to write our own... but this isn't quite the case - for the container to be able create a component it needs:
  • A publicly accessible constructor.
  • All dependencies to be registered in the container.
  • Mechanisms to allow for configuration and dependencies to be injected via constructors, or properties.
Which is fine for classes you own, but what about those that you don't - well you have a few options, but one of the easy options is to create a factory and get the container to use the factory for creating instances - to do this we'll be using a facility.

Facilities are "add-ins" for the container, they can be registered in the container, and augment what the container is capable of doing - there are a lot of facilities for the container, and many of them are documented (to varying degrees) on the castle project wiki ... we will be using a couple of different facilities in this part, first off will be the factory support facility.

So let's start off with a class that's supplied to us by a 3rd party... I'm just going to make one as an example, to keep things simple, called the Sms Service, for sending simple messages to cellular phones...

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;

 

        internal string UserName

        {

            get { return _userName; }

        }

 

        internal string Password

        {

            get { return _password; }

        }

 

        public int RetryAttempts

        {

            get { return _retryAttempts; }

            set { _retryAttempts = value; }

        }

 

        public void SetCredentials(string userName, string password)

        {

            _userName = userName;

            _password = password;

        }

    }

}


It also has a corresponding interface:

public interface ISmsService

{

    void SendMessage(string number, string message);

}


Now the point is that this class can not be constructred and configured by the container "as-is" because it requires something like this to happen:

SmsService service = new SmsService();

 

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

config.SetCredentials("joe", "secret");

config.RetryAttempts = 3;

 

service.SetConfig(config);


Ack! Which doesn't fit in nicely with our concepts of constructor and setter injection for configuration...  so the answer is first off, to write a factory... can you guess what it'll look like?

public class SmsServiceFactory

{

    public ISmsService CreateService()

    {

        SmsService service = new SmsService();

 

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

        config.SetCredentials("joe", "secret");

        config.RetryAttempts = 3;

 

        service.SetConfig(config);

 

        return service;

    }

}


Well almost - but we don't like hard coding credentials, so we might refactor it a little... to say something like this:

public class SmsServiceFactory

{

    private string _userName;

    private string _password;

    private int _retryAttempts = 3;

 

    public SmsServiceFactory(string userName, string password)

    {

        _userName = userName;

        _password = password;

    }

 

    public int RetryAttempts

    {

        get { return _retryAttempts; }

        set { _retryAttempts = value; }

    }

 

    public ISmsService CreateService()

    {

        SmsService service = new SmsService();

 

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

        config.SetCredentials(_userName, _password);

        config.RetryAttempts = _retryAttempts;

 

        service.SetConfig(config);

 

        return service;

    }

}


Now how do we use this factory in lieu of registering the SmsService itself in the container... well first off, we need to add in the factory support facility... which is placed within a new part of the castle configuration we haven't seen until now (so far we've only be using the <components /> section) - here's how that looks:

<configuration>

 

  <configSections>

    <section name="castle"

        type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor" />

  </configSections>

 

  <castle>

    <facilities>

 

      <facility

        id="factorysupport"

        type="Castle.Facilities.FactorySupport.FactorySupportFacility, Castle.MicroKernel" />

 

    </facilities>


Nothing much to it, but now the factory support facility has augmented our container, so we can do this:

<configuration>

 

  <configSections>

    <section name="castle"

        type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor" />

  </configSections>

 

  <castle>

    <facilities>

 

      <facility

        id="factorysupport"

        type="Castle.Facilities.FactorySupport.FactorySupportFacility, Castle.MicroKernel" />

 

    </facilities>

    <components>

 

      <component id="smsService.Factory"

                type="IoC.Tutorials.Part11.SmsServiceFactory, IoC.Tutorials.Part11">

        <parameters>

          <userName>joe</userName>

          <password>secret</password>         

        </parameters>

      </component>

 

      <component id="smsService.default"

                type="IoC.Tutorials.Part11.ISmsService, IoC.Tutorials.Part11"

                factoryId="smsService.Factory"

                factoryCreate="CreateService" />

 

    </components>

  </castle>

 

</configuration>


Notice that we've registered our factory as a component, and called it smsService.Factory - and then we've registered the smsService.default (interface only) and added a couple of additional attributes, factoryId (which references our factory component) and factoryCreate - the name of the method in the factory which is responsible for creating instances of our sms service.

Because we now have the factory support facility installed, whenever a component is registered that facility will inspect it and see if the factoryId attribute appears in the components configuration and consequently defer it's activation to the referenced factory - pretty cool huh?

So, the million dollar question, does it work?  Well lets see... here's our code:

static void Main(string[] args)

{

    WindsorContainer container = new WindsorContainer(new XmlInterpreter());

 

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

    smsService.SendMessage("+465556555", "testing testing...1.2.3");

 

    Console.Read();

}


And the output:

SMS message: testing testing...1.2.3 sent to: +465556555 with account: joe

At this point I was going to take a quick look into another factory-related facility, the TypedFactory, but it's currently broken in the main trunk ;o) so we'll wait until that's been resolved before finishing off this post.

Next time we'll have a quite look at revisiting a class design pattern, the decorator, when using the Windsor container.
posted @ Wednesday, April 25, 2007 7:11:04 PM (New Zealand Standard Time, UTC+12:00)    Comments [0] | |
10_setter_injection.png
So, lets have a look at setter injection - for this part I'll be refactoring the example in part 9 ... so if you recall in the last part we had a class that could send messages (to the console at least) - and it had a hard-coded string being used for the format... we'll I think it would be nice to "plug in" different message formatting, if we needed to... so first thing to do is create a necessary abstraction for formatting a message - which I've called the IMessageFormatter interface:

public interface IMessageFormatter

{

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

}


Now, our old method for formatting a message (as part of the SecretMessageSender class) used to look like this:

public void SendMessage(string to, string body)

{

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

}


So we just refactor that out into it's own class, like so:

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 update the secret message sender to use this default formatter... by default!

public class SecretMessageSender

{

    private readonly IEncoder _encoder;

    private readonly string _from;

    private IMessageFormatter _formatter = new DefaultFormatter();

 

    public SecretMessageSender(string from, IEncoder encoder)

    {

        _from = from;

        _encoder = encoder;

    }

 

    public IMessageFormatter Formatter

    {

        get { return _formatter; }

        set { _formatter = value; }

    }

 

    public void SendMessage(string to, string body)

    {

        string encodedBody = _encoder.Encode(body);

        Console.WriteLine(_formatter.FormatMessage(_from, to, encodedBody));

    }

}


Now notice we automatically create a default formatter for the class to use... so at this point we can run the program just as in part 9 (Without having to make any changes to the container configuration) and everything works as it did... however, we can also optionally override the message formatter by registering an implementation in the container... the MicroKernel is smart enough to discover any publicly accessible properties with setters, look for any implementations, and inject them if they're registered in the container.

So first off lets create a different implementation - I'm going to use NVelocity (a template engine, which is used for one of the View engines that comes with monorail) this time along with a template - so first we have the alternative message formatter class:

public class NVelocityMessageFormatter : IMessageFormatter

{

    private readonly VelocityEngine _velocity;

    private readonly Template _template;

 

    public NVelocityMessageFormatter(string templateFile)

    {

        _velocity = new VelocityEngine();

        ExtendedProperties props = new ExtendedProperties();

        _velocity.Init(props);

        _template = _velocity.GetTemplate(templateFile);

    }

 

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

    {

        VelocityContext context = new VelocityContext();

        context.Put("from", from);

        context.Put("to", to);

        context.Put("body", body);

        context.Put("today", DateTime.Now);

 

        StringWriter writer = new StringWriter();

        _template.Merge(context, writer);

 

        return writer.ToString();

    }

}


And of course, we also need a template file (Which we will call message.vm) - this is what our template will look like:

 To:   $to

 From: $from

 Sent: $today

 

 ----------------------

 

 $body

 

 ----------------------


And finally the last part of the puzzle is to update the container configuration to include our alternative message formatter:

<configuration>

 

  <configSections>

    <section name="castle"

        type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor" />

  </configSections>

 

  <castle>

    <components>

      <component id="encoder.silly"

                service="IoC.Tutorials.Part10.IEncoder, IoC.Tutorials.Part10"

                type="IoC.Tutorials.Part10.SillyEncoder, IoC.Tutorials.Part10" />

 

      <component id="encoder.null"

                service="IoC.Tutorials.Part10.IEncoder, IoC.Tutorials.Part10"

                type="IoC.Tutorials.Part10.NullEncoder, IoC.Tutorials.Part10" />

 

      <component id="messageSender"

                type="IoC.Tutorials.Part10.SecretMessageSender, IoC.Tutorials.Part10">

        <parameters>SecretMessageSender

          <from>alex@bittercoder.com</from>

          <encoder>${encoder.null}</encoder>         

        </parameters>

      </component>

 

      <component id="fancyMessageFormatter"

                service="IoC.Tutorials.Part10.IMessageFormatter, IoC.Tutorials.Part10"

                type="IoC.Tutorials.Part10.NVelocityMessageFormatter, IoC.Tutorials.Part10">

        <parameters>

          <templateFile>message.vm</templateFile>

        </parameters>

      </component>

 

    </components>

  </castle>

 

</configuration>


And now if we give it a run, we get this output:

To:   hammet
From: alex@bittercoder.com
Sent: 25/04/2007 6:56:37 p.m.

----------------------

castle is great!

----------------------


So you can now see how a mix of constructor and setter injection can be used to achieve compulsory and optional dependencies - of course, we can also wire up properties to specific implementations - for instance in this last example we could change the config to read:

<component id="messageSender"

          type="IoC.Tutorials.Part10.SecretMessageSender, IoC.Tutorials.Part10">

  <parameters>SecretMessageSender

    <from>alex@bittercoder.com</from>

    <encoder>${encoder.null}</encoder>

    <Formatter>${fancyMessageFormatter}</Formatter>

  </parameters>

</component>

 

<component id="defualtMessageFormatter"

    service="IoC.Tutorials.Part10.IMessageFormatter, IoC.Tutorials.Part10"

    type="IoC.Tutorials.Part10.DefaultFormatter, IoC.Tutorials.Part10" />       

 

<component id="fancyMessageFormatter"

          service="IoC.Tutorials.Part10.IMessageFormatter, IoC.Tutorials.Part10"

          type="IoC.Tutorials.Part10.NVelocityMessageFormatter, IoC.Tutorials.Part10">

  <parameters>

    <templateFile>message.vm</templateFile>

  </parameters>

</component>


Where even though the default message formatter is registered first in the container, the fancy message formatter will be used because it's manually wired up in the messageSender's component parameters.

Next time will be having a look at factories and how to fit in with the Windsor container.
posted @ Wednesday, April 25, 2007 6:43:10 PM (New Zealand Standard Time, UTC+12:00)    Comments [0] | |
# Friday, April 20, 2007
I noticed that Ivan posted a list of tutorials etc. on his blog... I think it's worth also adding that there is a site dedicated to these kinds of resources, as well as snippets, recipes etc.  - it's still in it's infancy, but I think it will end up being quite invaluable as a resource for castle project users (here's hoping at any rate!)

http://using.castleproject.org/

posted @ Friday, April 20, 2007 9:19:00 AM (New Zealand Standard Time, UTC+12:00)    Comments [2] | |
# Thursday, April 19, 2007
So the first 9 posts are up for the container tutorial series...  but I haven't made much mention of what can be done to play around with the windsor container yourself while reading this series.

Well first-off ... my thoughts on getting started with the Castle project are generally practical, first off I think it's worth grabbing the second release candidate - check out what castle can do, have a general play, maybe try to generate a monorail project and get it working... and then ... well I would probably uninstall it, and grab the latest cut of the castle project and contributed projects from svn and build it yourself using nant.

This gives you opportunities to use all the "new stuff" that gets added day by day (as well as bug fixes) but also ensures your actually capable of building and contributing patches for any issues you discover.

But that's a bit of an ask for someone experimenting, especially if you don't know anything about svn... so essentially for playing around with the basics of the windsor container, you only need 4 Castle assemblies from the bleeding edge, and I'll give them to you:

simple_container_references.png

And to make life easy I included those assemblies in a folder called "SharedLibs" as part of the following zip file, which contains the code for the first 9 parts... I'll do another code drop at the end of the container tutorials to round out the series for the sake of posterity... but everything you need for the first 9 tutorials is here:

Files for Parts 1 thru 9

Good Times ;o)


posted @ Thursday, April 19, 2007 10:31:40 PM (New Zealand Standard Time, UTC+12:00)    Comments [4] | |
9_constructor_injection.png

Constructor injection - so far inadvertantly we've been using setter inject to get our configuration information into our components... but you can also use constructors... the useful aspect of constructors is that it makes those parameters compulsory...

So lets take a look at the code for this post, first off there's an interface for a service which takes care of encoding a string for us:

public interface IEncoder

{

    string Encode(string source);

}


And then we have no classes which implement this service, one we can use when testing to not encode things at all - and another which encodes a string using our particularly strong "silly" encryption...

NullEncoder.cs

public class NullEncoder : IEncoder

{

    public string Encode(string source)

    {

        return source;

    }

}


SillyEncoder.cs

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;

    }

}


When then have a class for sending messages (currently we just send it to the console, so we can print them out and paste them onto the back of postcards) ... so lets have a look at that class:

public class SecretMessageSender

{

    private readonly IEncoder _encoder;

    private readonly string _from;

 

    public SecretMessageSender(string from, IEncoder encoder)

    {

        _from = from;

        _encoder = encoder;

    }

 

    public void SendMessage(string to, string body)

    {

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

    }

}


Notice the lack of default constructor, and that the constructor also takes an instance of type IEncoder... now Castle is smart enough to do two things for us:
  • Throw an exception if we try to get an isntance of SecreteMessageSender without having set the from configuration parameter.
  • Find the default implementation of the IEncoder registered in the container, and to supply that as the value for the second argument in the constructor.
So lets have a look at the application itself:

static void Main(string[] args)

{

    WindsorContainer container = new WindsorContainer(new XmlInterpreter());

 

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

 

    sender.SendMessage("hammet", "castle is great!");

 

    Console.Read();

}


And finally our configuration:

<configuration>

 

  <configSections>

    <section name="castle"

        type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor" />

  </configSections>

 

  <castle>

    <components>

      <component id="encoder.silly"

                service="IoC.Tutorials.Part9.IEncoder, IoC.Tutorials.Part9"

                type="IoC.Tutorials.Part9.SillyEncoder, IoC.Tutorials.Part9" />

 

      <component id="encoder.null"

                service="IoC.Tutorials.Part9.IEncoder, IoC.Tutorials.Part9"

                type="IoC.Tutorials.Part9.NullEncoder, IoC.Tutorials.Part9" />

 

      <component id="messageSender"

                type="IoC.Tutorials.Part9.SecretMessageSender, IoC.Tutorials.Part9">

        <parameters>SecretMessageSender

          <from>alex@bittercoder.com</from>

        </parameters>

      </component>

 

    </components>

  </castle>

 

</configuration>


So you can see we've registered both implementations of the encoder, with the silly encoder being first - so as mentioned in the last part - this will be the default - and we also register our message sender (with the required from parameter)... so what happens when we run it:

to: hammet
from: alex@bittercoder.com

CYSQLD IS ERDYQ!


Cool... but what if wanted to send an unencrypted message... well we have a few options:
  • Swap the order in which the implementations are registered
  • Remove / comment out any implementations we don't want (so comment out the silly encoder)
  • Or reference the implementation we specifically want to wire up to, using it's identifier...
So lets have a look at the last one...

<configuration>

 

  <configSections>

    <section name="castle"

        type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor" />

  </configSections>

 

  <castle>

    <components>

      <component id="encoder.silly"

                service="IoC.Tutorials.Part9.IEncoder, IoC.Tutorials.Part9"

                type="IoC.Tutorials.Part9.SillyEncoder, IoC.Tutorials.Part9" />

 

      <component id="encoder.null"

                service="IoC.Tutorials.Part9.IEncoder, IoC.Tutorials.Part9"

                type="IoC.Tutorials.Part9.NullEncoder, IoC.Tutorials.Part9" />

 

      <component id="messageSender"

                type="IoC.Tutorials.Part9.SecretMessageSender, IoC.Tutorials.Part9">

        <parameters>SecretMessageSender

          <from>alex@bittercoder.com</from>

          <encoder>${encoder.null}</encoder>

        </parameters>

      </component>

 

    </components>

  </castle>

 

</configuration>


Notice the way the parameter is formatted - instead of the markup for a property reference which starts with a hash (#) we start service references with a dollar sign ($) and then surround the components identifier with braces.

And the results of running the app now:

to: hammet
from: alex@bittercoder.com

castle is great!


And thats our first look at constructor injection... we will revisit constructor injection again in later posts, however the next part will look at setter injection.
posted @ Thursday, April 19, 2007 9:37:05 PM (New Zealand Standard Time, UTC+12:00)    Comments [0] | |

8_implementations_by_key.png
So far we've looked at registering one implementation for any one service, you could call them the "default" implementation, because it's the implementation the container returns when you ask for that service... but your not limited to only having one implementation registered, and the way to do this is by giving each implementation that's registered a unique key.

There are many reasons for doing this... but in this example we'll look at one reason - because we want to vary the configuration info used...

So here's our component's code:

public class FileReader

{

    private string _fileName;

 

    public string FileName

    {

        get { return _fileName; }

        set { _fileName = value; }

    }

 

    public string ReadToEnd()

    {

        return File.ReadAllText(_fileName);

    }

}


It's a simple class which lets us read the contents of a file as many times as we like... so we're going to try registering it twice, with different configurations (and different identifiers) in the container.

<configuration>

 

  <configSections>

    <section name="castle"

        type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor" />

  </configSections>

 

  <castle>

    <components>

      <component id="reader.file1" type="IoC.Tutorials.Part8.FileReader, IoC.Tutorials.Part8">

        <parameters>

          <FileName>file1.txt</FileName>

        </parameters>

      </component>

      <component id="reader.file2" type="IoC.Tutorials.Part8.FileReader, IoC.Tutorials.Part8">

        <parameters>

          <FileName>file2.txt</FileName>

        </parameters>

      </component>

    </components>     

  </castle>

 

</configuration>


So far so good, lets have a look at the app itself - notice that the file1Reader and file2Reader instances are "resolved" with an extra parameter - which is the id, or key, used to select a particular implementation... but what about the default instance, which reader will that be?

static void Main(string[] args)

{

    WindsorContainer container = new WindsorContainer(new XmlInterpreter());

 

    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());

 

    Console.Read();

}


And here's the results of running the program:

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 you can see that file1Reader and defaultReader are the same - and file1Reader was the first FileReader to be registered in the container -and that's the rule, the first one registered is the default... which is another example of convention over configuration with Castle, rather then having to explicity denote which is the default with some more xml noise.

Though with a little thinking you can find plenty of ways to access implementations by key to solve certain problems, for the unimaginative ... how about an application where you can provide a uri to send plain text messages to ... and depending on the scheme you need to find an implementation that can do the work of sending the message.

You have a bunch of destinations, addressed by Uri...
  • file://c:/temp/log.txt
  • ftp://ftp.google.com/log.txt
  • http://www.bittercoder.com/SimpleMessageService.aspx
  • fax://64215559555
And then you can just register the implementations/schemes you wish to support...
  • messageSender.file
  • messageSender.ftp
  • messageSender.http
  • messageSender.fax
And then look them up as required, using something like

Uri uri;

// blah blah blah

string key = "messageSender."+ uri.Scheme;

if (container.Kernel.HasComponent(key))

{

    ISender sender = container.Resolve<ISender>(key);

    // send the message at this point...

    sender.SendMessage("hi there");

}

else

{

    // no implementation registered...

    throw new NotImplementedException("no sender registered for scheme: " + uri.Scheme);

}


Personally I wouldn't do this ;o) but there's certainly no technical reason why you couldn't... notice how we check that a component is registered for that key - we could just let the container throw an exception... but then we wouldn't know how to check that a container has a certain key registered in it, would we!

The next part will be on constructor injection... and following that setter injection.
posted @ Thursday, April 19, 2007 7:23:14 PM (New Zealand Standard Time, UTC+12:00)    Comments [0] | |
# Wednesday, April 18, 2007

So I've decided to do a quick little series on the windsor container - all up It'll probably cover 15 to 20 posts... each one should be very short, covering some small concept... just a little nugget.

This series will be a little different then most discussions on IoC and containers... rather then get in your face with concepts like dependency injection, and encouraging testability, it's just going to focus on the container itself, and the ways you can use it... I'm not sure if it'll be of any value, but If nothing else to gets me back into blogging regularly.

The first 7 parts are already up:

I'll be posting them in batches... so the series should be finished within a week.

posted @ Wednesday, April 18, 2007 7:51:40 AM (New Zealand Standard Time, UTC+12:00)    Comments [4] | |
# Tuesday, April 17, 2007
7_switching_implementations.png
So this time we're going to look at how you can not only change configuration for a component at runtime, but actually change which component is doing the work for us... powerful stuff :)

So the "trick" here is to abstract out what features we expect our component to support from it's implementation, and stuff those into an interface... so in this case I have an idea for a simple service which lets us get the "message of the day" - so lets look at my interface:

public interface IMessageOfTheDay

{

    string GetMessageOfTheDay();

}


Now we have two implementations of this service, one that lets us have a static message set via configuration:

public class StaticMessageOfTheDay : IMessageOfTheDay

{

    private string _message;

 

    public string Message

    {

        set { _message = value; }

    }

 

    public string GetMessageOfTheDay()

    {

        return _message;

    }

}


And another, which goes to wiki quotes and grabs the quote of the day:

public class WikiQuotesMessageOfTheDay : IMessageOfTheDay

{

    public string GetMessageOfTheDay()

    {

        WebClient client = new WebClient();

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

 

        string toFind = "<div style=\"background: #fff5f5\">";

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

        int length = content.IndexOf("<a", start) - start;

 

        return content.Substring(start, length);

    }

}


so - our program is pretty simple:

private static void Main(string[] args)

{

    WindsorContainer container = new WindsorContainer(new XmlInterpreter());

 

    IMessageOfTheDay motd = container.Resolve<IMessageOfTheDay>();

 

    Console.WriteLine("MOTD: {0}", motd.GetMessageOfTheDay());

 

    Console.Read();

}


And so how do we swap between implementations, well we need to introduce an additional attribute to our components configuration called "service" where we specifiy what service our component implements... in this case it will be "IMessageOfTheDay" - so heres the configuration when using the Static MOTD class:

<configuration>

 

  <configSections>

    <section name="castle"

        type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor" />

  </configSections>

 

  <castle>

    <components>

      <component id="motd.service"

                service="IoC.Tutorials.Part7.IMessageOfTheDay, IoC.Tutorials.Part7"

                type="IoC.Tutorials.Part7.StaticMessageOfTheDay, IoC.Tutorials.Part7">

        <parameters>

          <message>Welcome to my container tutorials</message>

        </parameters>

      </component>

    </components>

  </castle>

 

</configuration>


And running the program gives us:

MOTD: Welcome to my container tutorials

But we can now swap to a different component with the same service at run-time, and get a different implementation... here's how that looks:

<configuration>

 

  <configSections>

    <section name="castle"

        type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor" />

  </configSections>

 

  <castle>

 

    <components>

      <component id="motd.service"

          service="IoC.Tutorials.Part7.IMessageOfTheDay, IoC.Tutorials.Part7"

          type="IoC.Tutorials.Part7.WikiQuotesMessageOfTheDay, IoC.Tutorials.Part7" />

    </components>

  </castle>

 

</configuration>


And now running the program gives us:

MOTD: Man is not an end but a beginning. We are at the beginning of the second week. We are children of the eighth day.

A quote from Thorton Wilder - exciting huh, this seperation between interface and implementation is what makes doing so many cool things with an Inversion of control container possible... soak up the idea.

Next time we'll take a look at getting different implementations by using their "key" - have you been wondering what the "id" attribute is for in our component definitions?? Well wonder no more.
posted @ Tuesday, April 17, 2007 11:34:46 PM (New Zealand Standard Time, UTC+12:00)    Comments [0] | |
6_switching_lifestyles.png
Switching lifestyles is the theme of this post... so what's that all about?

Well first off - what is a lifestyle, in basic terms it specifies how many instances will be available at any one time from the container - so at the one extreme we have components with a transient lifestyle, where any requests from those components will return new instances - and at the opposite end of the spectrum we have singleton components, where there is only one instance for the whole container - there are other types of lifestyle, but we'll leave those for another post.

So first off - castle is all about convention over configuration, and by convention a component in the container is a singleton... so in this example we'll look into ways in which you can switch a components lifestyle to being transient.

First off, heres our component:

public class AddingService

{

    private int _total = 0;

 

    public void AddAmmount(int ammount)

    {

        _total += ammount;

    }

 

    public int Total

    {

        get { return _total; }

    }

}


It lets us add stuff... how neat is that... lets see our program:

private static void Main(string[] args)

{

    WindsorContainer container = new WindsorContainer(new XmlInterpreter());

 

    AddingService sheepCounted = container.Resolve<AddingService>();

    AddingService catsHerded = container.Resolve<AddingService>();

 

    sheepCounted.AddAmmount(10);

    sheepCounted.AddAmmount(50);

 

    catsHerded.AddAmmount(3);

    catsHerded.AddAmmount(12);

 

    Console.WriteLine("You have counted {0} sheep and herded {1} angry cats", sheepCounted.Total,

                      catsHerded.Total);

 

    Console.Read();

}


And if we run it:

You have counted 75 sheep and herded 75 angry cats

That doesn't seem right - our service is retaining a count, so we want a fresh instance of the class every time we request it - which means we should shift our component to the "transient" lifestyle - lets have a go at doing it with configuration, by adding the lifestyle attribute to the components definition.

<configuration>

 

  <configSections>

    <section name="castle"

        type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor" />

  </configSections>

 

  <castle>

    <components>

      <component id="adding.service" type="IoC.Tutorials.Part6.AddingService, IoC.Tutorials.Part6" lifestyle="transient" />

    </components>

  </castle>

 

</configuration>


And now if we run it again:

You have counted 60 sheep and herded 15 angry cats

That looks a bit better... but I propose that in many cases when your writing a component you know what it's lifestyle should be, before it's ever registered in a container - for instance in this case this class should always be transient, so we can actually decorate the class with a "Transient" attribute and can skip having to put the lifestyle in the configuration, this is how that would look:

[Transient]

public class AddingService

{

    private int _total = 0;

 

    public void AddAmmount(int ammount)

    {

        _total += ammount;

    }

 

    public int Total

    {

        get { return _total; }

    }

}


There are other lifestyles available to use - it's worth having a look through the castle wiki for more details... and we'll probably cover them in another post.

In the next part we will cover switching out implementations of components themselves.

posted @ Tuesday, April 17, 2007 11:12:30 PM (New Zealand Standard Time, UTC+12:00)    Comments [2] | |

5_config_parameters.png
So in this part we're going to look at configuration parameters - parameters let you consolidate or seperate individual configuration parameters away from the components themselves, in this case we are going to create 2 config files, one for parameters to use in the live system, and the other for parameters in the debug system.

The advantage with this approach is that you don't have to duplicate the component registrations, you can leave those in one place (for the example, we just put them in the app.config)... so lets start by looking at our two sets of property configurations...
  • properties-debug.config
  • properties-live.config
properties-debug.config

<configuration>

  <properties>

    <configName>Debug</configName>

  </properties>

</configuration>


properties-live.config

<configuration>

  <properties>

    <configName>Live</configName>

  </properties>

</configuration>


And now the app.config...

<configuration>

 

  <configSections>

    <section name="castle"

        type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor" />

  </configSections>

 

  <castle> 

    <components>

      <include uri="file://properties-debug.config" />

      <!--<include uri="file://properties-live.config" />-->

 

      <component id="whatConfig.service" type="IoC.Tutorials.Part5.WhatConfigurationService, IoC.Tutorials.Part5">

        <parameters>

          <Configuration>#{configName}</Configuration>

        </parameters>

      </component>

    </components>

  </castle>

 

</configuration>


Notice how the components configuration value has a hash (#) and some braces surrounding the word "configName" - that causes castle to look up the value of the property by the same name (which we declared in the property config file).

The application code is the same as part 4.

A common approach when working with developers who may need different configurations is to <include/> a file called say properties.config that contains all the configuration values that need to change between machines, and to not check that into source control... Be sure to also keep a "master" copy of the properties, say "master-properties.config" which provides a template for developers to create their own configuration (it's not a bad place to stick the instructions for doing this as well).


posted @ Tuesday, April 17, 2007 10:30:56 PM (New Zealand Standard Time, UTC+12:00)    Comments [0] | |
4_switching_configs.png
So, we have all this stuff in a configuration file... but what if we have two sets of configuration we want to swap between - perhaps one for test and one for live... well here's one way of doing it with the Windsor container.

So this is our component, we use it for demonstrating which configuration is loaded:

public class WhatConfigurationService

{

    private string _configuration;

 

    public string Configuration

    {

        get { return _configuration; }

        set { _configuration = value; }

    }

}


Now here's the applications code:

private static void Main(string[] args)

{

    WindsorContainer container = new WindsorContainer(new XmlInterpreter());

 

    WhatConfigurationService whatConfiguration = container.Resolve<WhatConfigurationService>();

 

    Console.WriteLine("Configuration: {0}", whatConfiguration.Configuration);

 

    Console.Read();

}


So we do this by seperating our configuration sets into different files... so we create two configuration files, called:

  • container-debug.config
  • container-live.config
And here's what they look like:

container-debug.config

<configuration>

    <components>

      <component id="whatConfig.service" type="IoC.Tutorials.Part4.WhatConfigurationService, IoC.Tutorials.Part4">

        <parameters>

          <Configuration>Debug</Configuration>

        </parameters>

      </component>

    </components>

</configuration>


container-live.config

<configuration>

  <components>

    <component id="whatConfig.service" type="IoC.Tutorials.Part4.WhatConfigurationService, IoC.Tutorials.Part4">

      <parameters>

        <Configuration>Live</Configuration>

      </parameters>

    </component>

  </components>

</configuration>


So if we've moved configuration into seperate files, how does the container know about them.... well, we use includes... so here's our main configuration file now:

<configuration>

 

  <configSections>

    <section name="castle"

        type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor" />

  </configSections>

 

  <castle>

    <!--<include uri="file://container-debug.config" />-->

    <include uri="file://container-live.config" />

  </castle>

 

</configuration>


So you can see that to shift between the debug and live configurations we just swap between including one configuration and another...

And when live is uncommented, running the program gives us this output:

Configuration: Live


There are other ways to achieve the same thing, but this is often the easiest to understand... also take careful note of that uri attribute on the include element... you don't just have to use the file:// scheme - you can include resources (embedded in your assemblies) or extend the resource subsystem with additional support for your own types of resources - but before you do, be sure to have a look at the list of out of the box possibilities here.

One question that was asked about during Architecture Camp was how container configuration could be synchronized between multiple servers, and includes provide one possibility, because you can place your shared configuration on a network share, or implement your own special resource type, that could for instance get the configuration from a webservice.

Next time we'll look at introducing configuration parameters, which is another way to deal with the problems of having to switch between configs at runtime - and can make your configuration easier to read and maintain too.

posted @ Tuesday, April 17, 2007 9:53:36 PM (New Zealand Standard Time, UTC+12:00)    Comments [0] | |
3_more_config_dictionaries.png

So in this part we look at creating a component which has a dictionary which gets configured... in this case we're creating a little service to handle word substitutions...

So lets have a look at the service:

public class AliasService

{

    private Dictionary<string, string> _aliases;

 

    public Dictionary<string, string> Aliases

    {

        get { return _aliases; }

        set { _aliases = value; }

    }

 

    public string Evaluate(string term)

    {

        if (_aliases == null) return term;

 

        while (_aliases.ContainsKey(term))

        {

            term = _aliases[term];

        }

 

        return term;

    }

}


And the application code that uses the service:

static void Main(string[] args)

{

    WindsorContainer container = new WindsorContainer(new XmlInterpreter());

 

    AliasService aliasService = container.Resolve<AliasService>();

 

    string sentence = "a dog ate my homework";

 

    foreach (string word in sentence.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries))

    {

        Console.Write("{0} ", aliasService.Evaluate(word));

    }

 

    Console.Read();

}


Our component is again registered without any parameters, lets run it and see what pearls of wisdom it can share:

a dog at my homework

Hmm... I'm not sure that's a great excuse for late delivery... let's do some configuration and try again:

<configuration>

 

  <configSections>

    <section name="castle"

        type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor" />

  </configSections>

 

  <castle>

    <components>

      <component id="aliases.service" type="IoC.Tutorials.Part3.AliasService, IoC.Tutorials.Part3">

        <parameters>

          <Aliases>

            <dictionary>

              <entry key="dog">duck</entry>

              <entry key="ate">broke</entry>

              <entry key="homework">code</entry>

            </dictionary>

          </Aliases>

        </parameters>

      </component>

    </components>

  </castle>

 

</configuration>


So, you can see we map keys to values via an entry key... and here's the result:

a duck broke my code

You may need to tweak the mappings, depending on what you actually broke...

Now at this point you might be wondering just how the strings are getting converted into strongly typed values for the last 3 parts - and to be honest, you won't need to know most of time, just do what "seems" right and it'll probably work... but when it doesn't, check out the castle projects wiki topic on component parameters, configuration and type converters.
posted @ Tuesday, April 17, 2007 9:14:30 PM (New Zealand Standard Time, UTC+12:00)    Comments [2] | |
2_more_config_arrays.png
So welcome to part 2, today we're going to look at some more config - this time it's arrays...

So we have a class, that tells us when we can down tools and goto the beach...

public class HolidayService

{

    private DateTime[] _holidays;

 

    public DateTime[] Holidays

    {

        get

        {               

            return _holidays;

        }

        set { _holidays = value; }

    }

 

    public bool IsHoliday(DateTime date)

    {

        if (_holidays != null)

        {

            DateTime matchDate = date.Date;

            foreach (DateTime test in Holidays)

            {

                if (test.Date.Equals(matchDate))

                {

                    return true;

                }

            }

        }

 

        return false;

    }

}


We can set the days we are allowed off by adding dates to the holidays array...

So lets look at our code for running this service:

internal class Program

{

    private static void Main(string[] args)

    {

        WindsorContainer container = new WindsorContainer(new XmlInterpreter());

 

        HolidayService holidayService = container.Resolve<HolidayService>();

 

        DateTime xmas = new DateTime(2007, 12, 25);

        DateTime newYears = new DateTime(2008, 1, 1);

 

        if (holidayService.IsHoliday(xmas))

            Console.WriteLine("merry xmas!");

        else

            Console.WriteLine("xmas is only for management!");

 

        if (holidayService.IsHoliday(newYears))

            Console.WriteLine("happy new year");

        else

            Console.WriteLine("new year, you haven't done all the work for last year!");

 

        Console.Read();

    }

}


The service configuration is just like last time, we have the component registered with no parameters... so if we run the program we shall see on the screen:

xmas is only for management!
new year, you haven't done all the work for last year!

Mum will be dissapointed, she'd done a roast 'n all... so lets get some configuration in their so we can have a few days off...

<configuration>

 

  <configSections>

    <section name="castle"

        type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor" />

  </configSections>

 

  <castle>

    <components>

      <component id="holidays.service" type="IoC.Tutorials.Part2.HolidayService, IoC.Tutorials.Part2" >

        <parameters>

          <Holidays>

            <array>

              <item>2007-12-24</item>

              <item>2007-12-25</item>

              <item>2008-1-1</item>

            </array>

          </Holidays>

        </parameters>

      </component>

    </components>

  </castle>

 

</configuration>


Now let's see if we're going to have a merry xmas and a happy new year - a quick run of our application....

merry xmas!
happy new year

You don't just have to use arrays either, you can do lists too - though I didn't show them here, just use list instead of array in the xml configuration...

See you for part 3 where we do dictionary configurations.
posted @ Tuesday, April 17, 2007 8:40:16 PM (New Zealand Standard Time, UTC+12:00)    Comments [0] | |
1_simple_configuration.png

Welcome to part 1... today we're looking at supporting basic configuration in components without additional coding by using the windsor container.

So - with the container we can provide configuration for a component which is loaded at runtime, so every time you start your app it will be read in - you can do this using the configuration support in .Net - but using castle makes support for this very code-light in comparison... let's take a look.

So first off, we have a class we can use to calculate the tax on a gross ammount:

public class TaxCalculator

{

    private decimal _rate = 0.125m;

 

    public decimal Rate

    {

        set { _rate = value; }

        get { return _rate; }

    }

 

    public decimal CalculateTax(decimal gross)

    {

        return Math.Round(_rate*gross, 2);

    }

}


By default the tax rate is 12.5% - but we can change the tax rate by setting the "Rate" property.

Now, lets look at setting up the container... so we have this code in our sample:

private static void Main(string[] args)

{

    WindsorContainer container = new WindsorContainer(new XmlInterpreter());

 

    TaxCalculator calculator = container.Resolve<TaxCalculator>();

 

    decimal gross = 100;

    decimal tax = calculator.CalculateTax(gross);

 

    Console.WriteLine("Gross: {0}, Tax: {1}", gross, tax);

    Console.Read();

}


The windsor container is constructed with an "XmlInterpreter" - this configuration will pull the setup for our container from a section in the App.config.

Let's have a look at that:

<configuration>

 

  <configSections>

    <section name="castle"

        type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor" />

  </configSections>

 

  <castle>

    <components>

      <component id="taxcalc.service" type="IoC.Tutorials.Part1.TaxCalculator, IoC.Tutorials.Part1" />

    </components>

  </castle>

 

</configuration>


Running the program will display: Gross: 100, Tax: 12.50

Now, what about changing the tax rate in the configuration?

<configuration>

 

  <configSections>

    <section name="castle"

        type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor" />

  </configSections>

 

  <castle>

    <components>

      <component id="taxcalc.service" type="IoC.Tutorials.Part1.TaxCalculator, IoC.Tutorials.Part1">

        <parameters>

          <Rate>0.25</Rate>

        </parameters>

      </component>

    </components>

  </castle>

 

</configuration>


Now running the program will display: Gross: 100, Tax: 25.00

And that's part 1 done - so now you can see how can we supply configuration parameters, and provide sensible defaults for them.

Next time we'll look at configuring arrays...

posted @ Tuesday, April 17, 2007 7:16:25 PM (New Zealand Standard Time, UTC+12:00)    Comments [0] | |
# Sunday, February 18, 2007
It seemed a long time coming, but finally Rhino Mock's 3.0 is available, which of course also means Dynamic Proxy 2 has made it to that sweet generic method support nirvana as well :)

I don't know where I'd be without these tools, I haven't done a .Net project without them in the last couple of years... in fact it's fueled my reluctance over the last couple of years for returning to bespoke development at any NZ dev shop which might dictate other (crappier) alternatives ;o)

I also noticed that mono is getting it's C# 3.0 support slowly sorted... Extension methods are in, as is some Lambda support... I need to sit down and spend some time thinking about how I should go about unit testing some of this stuff, it's on my list of "testing" things to do right after getting to grips with RhinoMocks 3 and perhaps writing another blog entry on mocking Base4 with all the new "goodies" - I need to do a monorail/base4 website for another little venture, so it's probably as good a time as any.

Went for a swim at Omaha today... just can't get enough of the beach this year - John Campbell turned up at the same time we did, there's only so many "Not in front of John" jokes I can handle in one day... or a life time ;o)
posted @ Sunday, February 18, 2007 7:11:28 PM (New Zealand Daylight Time, UTC+13:00)    Comments [0] | |
# Tuesday, February 13, 2007
Found myself writing a simple class for implanting "trial" logic for a client (as in you have 30 days left of your trial etc.) ... it relies on the current date and time, and so you can never really be assured your tests are robust unless you can control the current date & time within the test fixture (in fact any time you find yourself writing DateTime.Now alarm bells should be going off... even worse is logic based on DateTime.Now where it's evaluated more the once for a single function).

In the past I've generally Implemented something like an "IClock" interface, which would have a method like "DateTime GetCurrentTime()" or whatever seemed appropriate to the situation... but I decided to go with the lightweight solution of delegates instead in the morning, if only because I was being lazy I didn't see the need for creating an entire interface for such a trivial requirement... so we have:

private DateTime _trialExpirey;

private int _maxExecutions;

private TimeSpan _trialDuration;

private Func<DateTime> _nowFunction;

 

public TrialUpdater(DateTime trialExpirey, int maxExecutions, TimeSpan trialDuration)

    : this(delegate { return DateTime.Now; }, trialExpirey, maxExecutions, trialDuration)

{

}

 

public TrialUpdater(Func<DateTime> nowFunction, DateTime trialExpirey, int maxExecutions, TimeSpan trialDuration)

{

    if (nowFunction == null) throw new ArgumentNullException("nowFunction");

 

    _nowFunction = nowFunction;

    _trialExpirey = trialExpirey;

    _maxExecutions = maxExecutions;

    _trialDuration = trialDuration;           

}


But I'm starting to wonder if this code doesn't smell a bit if I start using it other places... for instance:
  • Could I supply an alternative delegate via the castle container...?
  • Could I mock out the nowFunction parameter easily using something like RhinoMocks and still have it participate in constraints...?
I'm thinking in the case of mocking it out you would probably need to implement some interfaces which lines up with the generic delegates (Func<Ret,T1,T2...> and Proc<T1,T2...> etc.) - so I would end mocking out an IFuncEvaluator<Ret> interface (or in this case IFuncEvaluator<DateTime>) -which would implement a method "T Evaluate();"... and the pass an anonymous delegate which in turn invokes the mocked IFuncEvaluator<Ret>.

Though maybe I've missed something and mocking out delegates is doable with the current RhinoMocks..?

As for being able to inject a value for the nowFunction parameter, I'm thinking a nice solution would be to actually wire it up to a method on another service declaratively i.e.

<component id="trialUpdater" type="MyLib.TrialUpdater, MyLib" >

  <parameters>

    <nowFunction>

      <method service="clockService" method="GetCurrentTime" />

    </nowFunction>

  </parameters>

</component>


Which I believe should be doable using a facility and a type converter... but I'm sure the devil's in the detail :)

At any rate, just a minor distraction, back to work.

As an aside the clocks a pretty boring example, but there are times when you want to manipulate the time for instance:
  • If you want to manipulate the time (return dates as UTC instead of Local)
  • Clamp the current Time so it's limited to a certain level of accuracy... perhaps you have an external expectation that all dates will be recorded at a 10ms level of accuracy (perhaps you want to align database timestamps with timestamps within your application).
  • Perhaps your application uses the clock to work with snapshots of your domain model in the past.
How many people are actually using anonymous delegates and generic Func<T...> / Proc<T...>'s in their day to day coding for tasks like this?

posted @ Tuesday, February 13, 2007 1:53:57 PM (New Zealand Daylight Time, UTC+13:00)    Comments [0] | |
# Saturday, November 11, 2006

Domain Driven Design Afterthoughts...

I just finished reading Jimmy Nilsson’s Applying Domain-Driven Design and Patterns [ADDDP] book... I actually read it cover to cover, something I’ve found difficult to compel myself to do with some of the other books that have been lying around my desk for a wee while now (such as Petzold’s “Applications = Code + Markup” – a great book to assault someone with in a dark alley)...

First off, I think this book is a pretty good, it didn’t cover a lot of new ground for me, but It’s very down to earth, which I liked, and it’s encouraged me to have a read of Evan’s and Fowler’s more definitive works on the subject too... I also liked the fact that this book does attempt to tie the whole story together, from rough sketch through to identifying the domains language, using TDD to build up your domain model and even some of the gritty integration work, including evaluating OR/M features, using NHibernate as an example, and even looks into inversion of control contains (spring sadly, it would’ve been great to have seen Castle get a mention) and finally AOP. On the down side – I think the book could’ve tackled the application of rules to your domain model a little better (I wanted to see more code) and depending on your TDD knowledge, you might find that a couple of the chapters don’t really do much for you as there’s little focus on the model so much as the key concepts of red, green, refactor...

At any rate, one thing I did keep rolling around in the back of my mind is just how Base4.Net fits into the “domain model” picture ... it’s difficult to nail down, there are plenty of mechanisms for implementing most of what you need to create a domain model, for instance:

  • Inheritance, though it’s support for discriminators in user types isn’t quite up to scratch – it only works via “ItemBase” at the moment – though I think Alex James mentioned that this would be implemented at some point... and though I haven’t tried, you could roll your own in some way.
  • Aggregates (through extended properties).
  • Various hooks (Events) to allow for the application of custom behavior, for instance you could wire up to a BeforeSave event on a type and implement some custom validation rules... not that easy to test though .
  • A reasonable query abstraction - Good query support.
  • A “logical” transaction mechanism, suitable for supporting the concept of a “UnitOfWork”, though it’s explicit, rather the implicit, and based on the examples in the documentation this could be a little annoying to work with when you’re trying to persist the entire graph for an aggregate – however using a similar implementation for “UnitOfWork” as Ayende does in the Rhino.Commons library for NHibernate I’m sure I could get it all working nicely, without too much trouble.

And it sounds like I’m on to a winner... but I think what I struggle with is that the types in your schema are not really the focal point for your domain model, because they’re not POCO, unlike say a domain model implemented with NHibernate as the backing O/RM can be, you can’t enrich or decorate them with additional functionality all that easily... It’s not that you have to build your domain model this way, it’s just that’s the way I would like to do it, at least to satisfy me that I'm not being railroaded into a bad design choice – but I think it’s the small blood price you pay for letting Base4 generate the schema assemblies for you, that loss of control is also a boon in immediate productivity when you start developing apps with Base4 apps... I’ve come close while using ActiveRecord, but it’s still not the same.

So... given the restrictions I’m left to implementing additional abstractions for my domain model... which means using repositories and services for encapsulating the business logic... which, in turn, brings me to mocking...

Mocking out my Base4 Implementation...

Now, if you recall a while back I talked about my repository implementation... basically it let you do things like:

IRepository<Order> orderRepository = IoC.Resolve<IRepository<Order>>();                       

 

Order orderForApples = new Order();

OrderLine greenOnes = new OrderLine();

OrderLine redOnes = new OrderLine();

orderForApples.OrderLines.Add(greenOnes);

orderForApples.OrderLines.Add(redOnes);

 

orderRepository.Save(orderForApples);

Big woop, but what I probably neglected to mention is that the repository is great for implementing a chain of generic decorators (which can be set up in your IoC container of course)... so at the bottom/base of the chain we may have our “Base4StorageRepository” and layered on top of that we might have various decorators (each injected with a dependency for the next repository in the chain) for implementing some useful concepts...

Things that spring to mind are:

  • Security
  • Validation
  • Logging

Being able to configure these things is quite useful, and there’s little stopping you deploying additional decorators as additional assemblies for an already installed product – just throw in some additional container configuration - and it is a great deal more elegant then implementing this functionality with AOP.

But you do kind of paint yourself in a corner at the same time... this generic decorator pattern stops you from being able to decorate the repository with additional methods for implementing business level functionality (because any decorations that are applied to your base repositorty will mask out  methods and properties no present in the IRepository<T> interface)... that’s fine though, I guess we just have to write the repository off as being more of a persistence mechanism, It’s really a logical separation of concerns anyway... you can decorate a "wrapper" at the top of the chain though (and this is how Ayende does, but lets ignore that for now ;o)

So... A higher level entity for dealing with the business level concerns is required... I call mine services, that may or may not sit right with you, but it makes reasonable sense in my application – and these service are injected as dependencies of the controllers re: MVC, yeah this is a Monorail app (or at least, part of it is)...

These services often aggregate the features of multiple repositories, like this catalogue service below which deals with a simple music structure:

public class CatalogueService : ICatalogueService

{

    public CatalogueService(IRepository<Track> trackRepository, IRepository<Release> releaseRepository,

                            IRepository<Artist> artistRepository, IRepository<Genre> genreRepository)

    {

        if (trackRepository == null) throw new ArgumentNullException("trackRepository");

        if (releaseRepository == null) throw new ArgumentNullException("releaseRepository");

        if (artistRepository == null) throw new ArgumentNullException("artistRepository");

        if (genreRepository == null) throw new ArgumentNullException("genreRepository");

 

        _trackRepository = trackRepository;

        _releaseRepository = releaseRepository;

        _artistRepository = artistRepository;

        _genreRepository = genreRepository;

    }

In this case we have a dependency on four different repositories...

For this example we have a pretty simple schema... with a child-parent relationship between Track, Release and Artist... and a Many to Many relationship between Tracks and Genres...

Track -> Release -> Artist
Track(s) <-> Genre(s)

The catalogue service implements the business rules for dealing with the catalogue, in some cases this is no more than querying the associated repository... so for getting a list of releases for a particular artist we have this (and yeah, I know it’s pretty daft):

public PagedItemList<Track> ListTracksForArtist(Artist artist, int pageSize, int pageNumber)

{

    ObjectQuery query = new ObjectQuery(typeof (Track));

    query.Scope.Add("Release");

    query.Scope.Add("Release.Artist");

    query.Path = (Track.Fields.Release.Artist.ID == artist.ID);

    query.Path.AddOrderBy("Name", OrderByDirection.Ascending);

 

    return _trackRepository.Find(query, pageSize, pageNumber);

}

I say daft because it doesn’t support sorting and filtering by a query... but it’s here to illustrate a point, and until the customer actually asks for these features I’m not going to bother building them :P

At any rate, the point is not to critique the service, but instead how can we test this catalogue service without being connected to a Base4 server... and of course it’s RhinoMocks to the rescue!

Mocking with RhinoMocks...

So here’s the guts of the test in mid-refactoring ... post red-green for those sticklers for the rules ;o) (there’s still plenty yet to clean up, but it would muddy the waters a bit for this example I think...)

[Test]

public void ListReleasesForArtist()

{           

 

    Artist artist = new Artist();

 

    PagedItemList<Release> releases = new PagedItemList<Release>(new ItemList<Release>(), 1, 10, 20);

 

    Func<bool, ObjectQuery, int, int> callback

        = delegate(ObjectQuery query, int pageNumber, int pageSize)

        {

            ObjectPath path = Release.Fields.Artist.ID == artist.ID;

            path.AddOrderBy("Name");

 

            Base4Assert.ArePathsEqual(path, query.Path);

            Base4Assert.AreScopesEqual(new string[] { "Artist" }, query.Scope);

            Assert.AreEqual(1, pageNumber, "pageNumber");

            Assert.AreEqual(10, pageSize, "pageSize");

            return true;

        };

 

 

    Expect.Call(_releaseRepository.Find(null, 1, 10)).Callback(callback).Return(releases);

 

    _mockRepository.ReplayAll();

 

    ICatalogueService service =

        new CatalogueService(_trackRepository, _releaseRepository, _artistRepository, _genreRepository);

 

    PagedItemList<Release> results = service.ListReleasesForArtist(artist, 1, 10);

    Assert.AreSame(releases, results);

 

    _mockRepository.VerifyAll();

}

Pretty chunky I know - but as more tests are added there will be opportunities for removing some of that duplicated effort... however the key points to take away are:

  • We don’t need to have the base4 service running.
  • We are actually testing the catalogue service’s interactions with the repositories, instead of relying on detecting expected side effects in the underlying storage.
  • We’re verifying the object path and scope for the query, as well as paging information, and insulating ourselves from difficult to detect changes (like forgetting to apply an object scope, which may have a severe impact on performance).

Just to complete the story, the mock repository was created in the Setup (as we use it for every test case)... here's the code for it:

[SetUp]

public void SetUp()

{

    _mockRepository = new MockRepository();

 

    _trackRepository = _mockRepository.CreateMock<IRepository<Track>>();

    _releaseRepository = _mockRepository.CreateMock<IRepository<Release>>();

    _artistRepository = _mockRepository.CreateMock<IRepository<Artist>>();

    _genreRepository = _mockRepository.CreateMock<IRepository<Genre>>();

}

It doesn’t stop us from incorrectly spelling an object scope I think compile time query support for ordering and scoping of an object query will help to make this a little more robust... small potatoes.

The callback in this case is a bit of a “bad smell” – there’s support in rhino mocks for parameter constraints, but the object paths and scopes are a little too complex to test using the out the box ones... though you can get surprisingly close, they are pretty powerful... but I believe you can write custom constraints yourself – which is something I’ll do for the next post (I’ve never done it before, I'm guessing it's easy) and hopefully that will reduce the complexity of these tests quite a bit, and replace the less concise anonymous delegate, and more importantly, make it easy to develop the catalogue service in a test-driven manor.

For those more observant people you may have noticed the “Base4Assert” as well – that’s a little static helper class I’m using in these tests... it’s not perfect, but it works for simple cases including things like multi-level scopes and gives meaningful failure methods like “expected scope ‘Release.Artist’ but found nothing.” Or "expected OrderBy Name Descending, but found OrderBy Name Ascending"... which can quickly narrow down problems for you, especially if your writing these tests first (which is the whole point of this exercise I feel).

Conclusion... For Now ;o)

Last thing I’ve done is to have tossed away a lot of the additional query overloads in my original repository design in favor of just using a single ObjectQuery parameter with and without page number and page size (returning a PagedItemList<T> when providing a page number and page size, and returning an IItemList<T> when querying without them) – It makes everything a lot more... predictable, and is a lot cleaner when you start considering generic decorator implementations (10 overloads is 10 more code paths that need testing in a decorator... ) - looking towards to the future it should conceivable that a compile time query will allow you to construct the entire object query, not just the unordered path, and I’m quite happy to build these up in a few lines of code before passing them to a find method for now.

Edit (Sunday 12th):

In a similar vein, I just noticed Ayende's great MSDN article this evening - which covers that whole IRepository<T> story, including generic decorators and most importantly the intricacies of registering and chaining these components in the windsor container... great stuff!

posted @ Saturday, November 11, 2006 12:00:12 AM (New Zealand Daylight Time, UTC+13:00)    Comments [3] | |
# Thursday, November 02, 2006

Castle goes RC2

Well it's an exciting week for Castle users, RC2 is out the door, and with it a new website look and feel with up-to-date content, and most interesting to me is the introduction of a new entity "CastleStronghold" a commercial venture, run by Hammet which offers professional support for developers and organisations implementing solutions in Castle, including guaranteed response times to inquiries and access to additional skilled development resources.

Personally Castle Stronghold is great news, as a developer for a company which has been using the Castle IoC for over a year now it adds a certain weight to our decision to run with this technology, and I think it offers a clear indication of the longevity this technology and product has... In time as our customer base grows it certainly looks appealing to have guaranteed support backing us up - and also helps customers to understand it's not some half backed open source project that's just going to fizzle out one day...

The RC2 release itself is exciting from a community point of view, it should be better then ever for people to pick up and play with this stuff - though we generally use interim snapshots of the trunk (ie. the last trunk release that didn't break our build...) so we've been exposed to most of the features for a while now, albeit without alot of the bug fixes ;o)

IronPython

I've been a bit quiet on the IronPython front... which is mostly because I haven't had the time to play around with it much lately - however I'll try to finish off my look into IronPython as a scripting engine, and in particular the good and bad aspects of getting it to play with your .Net code... In the mean time a collection of useful IronPython links is slowly growing here: http://ironpython-urls.blogspot.com/

Base4.Net

A week into using the Base4.Net's latest release, with compile-time query support, I'm loving it... it definitely gives a huge leap in productivity and expressability (if that's even a word ;o) - looking forward to seeing these features rounded out at some point (with support for scopes, projections and ordering) - Alex James is talking about migrations (my "most-wanted" feature) and it's looking encouraging, it's where I feel the most pain at the moment as base4 isn't particularly friendly when you try to approach the problem of building your schema in a YAGNI fashion - there is quite a bit of pain involved in adding and removing properties from types during development as requirements are refined.

The rub is that the current "on the table" solution will require restarting the base4 service to apply the migration... which at the moment means restarting the windows service with a different command line... or more likely, stopping the service, then starting the standalone server with the right command line arguments, waiting till it's done, stopping the standalone server and starting the service again...  I was originally thinking of implementing these as a Nant or MSBuild task (much like RoR's migrations work with rake) but I think it might be a bit chunky... I need to think about it a bit more.

Splicer

I haven't forgot about my little side project (Splicer is a library I've written for "attempting" to eliminate the pain of using DirectShow.Net to encode audio and video) - and I do intend to keep updating and supporting it as-needed ... next release should see WinForm samples for encoding audio and video added, and updated code examples... after that I might review the implementation a bit, to see how effects and transitions can be made easier to use via relative times - I'm interested in DSL's at the moment, so maybe I could create a DSL for video editing ;o)... if nothing else it would be amusing... I've yet to establish if anyone actually uses the library yet (other than myself of course).

posted @ Thursday, November 02, 2006 12:33:00 PM (New Zealand Daylight Time, UTC+13:00)    Comments [2] | |
# Tuesday, October 31, 2006

Though I knew you could do it, I never have till today... and that's supplying a type for a generic parameter in another type, which is registered in a container... Of course I didn't have to do it that way, but it it kept the configuration a little thinner.

Basically I have some simple WCF services I wanted to host in a container.. here's the service's interface...

[ServiceContract(Namespace="http://localhost/schemas/testrunner/", SessionMode=SessionMode.Required)]

public interface ITestRunner

{

    [OperationContract]

    Guid StartTestRun(Guid testSuiteId);

 

    [OperationContract]

    TestRunStatus GetRunStatus(Guid testRunId);

}

To get this to work for my implementation I had to do one thing, which was set the InstanceContextMode to "single" for the service implementations behaviour, otherwise the service host would die when I tried to pass in an instance (it expects a type for any other mode)... I haven't dug very deep into WCF, but it would be nice if they supported a mechanism for supplying a component activator instead...

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]

public class TestRunner : ITestRunner

{

Now, I build a component for hosting my service... it implements IStartable...

public class HostingWrapper<T> : IStartable

    where T: class

{

    private ServiceHost _host;

    private T _service;

    private ILogger _log;

 

    public HostingWrapper(ILogger log, T service)

    {

        if (log == null) throw new ArgumentNullException("log");

        if (service == null) throw new ArgumentNullException("service");

 

        _log = log;

        _service = service;       

    }

 

    public void Start()

    {

        _host = new ServiceHost(_service);

        if (_log.IsDebugEnabled) _log.Debug("Opening ServiceHost for service: {0}", _service.GetType());

        _host.Open();

        if (_log.IsInfoEnabled) _log.Info("Opened ServiceHost for service: {0}", _service.GetType());

    }

 

    public void Stop()

    {

        if (_log.IsDebugEnabled) _log.Debug("Closing ServiceHost for service: {0}", _service.GetType());

        _host.Close();

        ((IDisposable)_host).Dispose();

        if (_log.IsInfoEnabled) _log.Info("Closed ServiceHost for service: {0}", _service.GetType());

        _host = null;

    }

}

And then you just need to regsiter it in the container's configuration:

<components>

    <component id="testRunnerService.default"

        service="BoatsForGoats.Services.Testing.ITestRunner, BoatsForGoats.Services"

        type="BoatsForGoats.Services.Testing.TestRunner, BoatsForGoats.Services" />

 

    <component id="testRunnerHost.default"

        type="BoatsForGoats.Services.HostingWrapper`1[[BoatsForGoats.Services.Testing.ITestRunner, BoatsForGoats.Services]], BoatsForGoats.Services" />

About the only tricky thing is that I guessed (incorrectly) that I would only need a single set of square brackets around the generic parameter.

.Net | castle | WCF
posted @ Tuesday, October 31, 2006 12:21:10 PM (New Zealand Daylight Time, UTC+13:00)    Comments [0] | |
# Thursday, October 19, 2006

I think there's 3 levels of skill involved with the Castle IoC implementation... first off you get a handle of the XML configuration, registering components, using existing facilities... pretty much getting away largely with cut 'n paste coding.

Then you get to the intermediate level.. writing basic facilities, tweaks to the component model, writing your own sub dependency resolvers or component activator, having a go with binsor configuration.

I think the third level is reserved for the Castle team alone... ;o)

This post is going to be straddling the beginner to intermediate kinda level... which is generally all I ever reach with Castle's IoC... it's not often you have to dig deeper day-to-day... though it's always good to know there is a lot of untapped potential there.

So.. for today, say you have a component, like the Base4Host, which has some explicit constructors:

public Base4Host(string appName, int port)

{

    if (string.IsNullOrEmpty(appName)) throw new ArgumentNullException("appName");

    if (port <= 1024) throw new ArgumentOutOfRangeException("port", "port should be greater then 1024");

    _appName = appName;

    _port = port;

}

 

public Base4Host(string appName, int port, string root)

    : this(appName, port)

{

    if (string.IsNullOrEmpty(root)) throw new ArgumentNullException("root");           

    _root = root;

}


You can register it the container easy enough, and provide values for them in XML configuration, but what if you want to do the same programatically... generally your first stop would be to examine the IWindsorContainer for a suitable overload... alas it doesn't get us far, so we dig in to the underlying IKernel itself... the kernel exposes some possible candidates:

void AddComponentWithExtendedProperties(String key, Type classType, IDictionary extendedProperties);

void AddComponentWithExtendedProperties(String key, Type serviceType, Type classType, IDictionary extendedProperties);


So you experiment with them, but supplying the dictionary of extended properties does nothing... hmm... time to file a bug report? well no... extended properties having nothing to do with satisfying parameter or property dependencies on your component - not directly at least.

So why don't we just create the component ourselves.. and then add it to the container?

Well you can, via the Kernel.AddComponentInstance method but you're going to miss out on some things... for instance the startable facility won't be "concerned" with your component, and as such if it implements IStartable it won't get started and stopped... Though I haven't confirmed this, I dont think the container will bother to dispose of any IDisposable components registered in this fashion either... the container doesn't consider itself the owner of the component (and generally this is what we want).

So we're going to have to get a little more intimate with the container implementation ... so every time a component is registered in the container a corresponding ComponentModel is generated for the component, this basically keeps track of the:
  • Components dependencies
  • Constructor candidates
  • Parameters (sounds like us...)
  • Name, implementation type and service type.
  • Lifecycle, Lifestyle...
  • And some other stuff you can discover for yourself.
Now we could get heavy handed and jump into contributing to the construction of the component model itself... but it's pretty uncessary, we just want to tweak the end result... so we can use an event handler on the Kernel - ComponentModelCreated.

So here we have an implementation that solves our problems... This is being implemented inside a facility, but you could do this anywhere... wire it up in your custom container that's derived from WindsorContainer maybe, obviously you want to remove the if statement for checking the Implemenation type is Base4Host though. :)

private const string AdditionalParametersKey = "AdditionalParameters";

 

private void Kernel_ComponentModelCreated(Castle.Core.ComponentModel model)

{

    if (model.Implementation == typeof(Base4Host))

    {

        if ((model.Configuration == null)

            && model.ExtendedProperties.Contains(AdditionalParametersKey))

        {

            Dictionary<string, object> additionalParameters = (Dictionary<string, object>)model.ExtendedProperties[AdditionalParametersKey];

            foreach (string parameterName in additionalParameters.Keys)

            {

                model.Parameters.Add(parameterName, Convert.ToString(additionalParameters[parameterName]));

            }

        }

    }

}

 

protected override void Init()

{

    Kernel.ComponentModelCreated += new ComponentModelDelegate(Kernel_ComponentModelCreated);

}


Now I can register my component by doing something like this:

Dictionary<string, object> additionalParameters = new Dictionary<string, object>();

additionalParameters.Add("appName", _applicationName);

additionalParameters.Add("port", _port);

additionalParameters.Add("root", _baseDirectory);

 

Hashtable properties = new Hashtable();

properties.Add(AdditionalParametersKey, additionalParameters);

 

Kernel.AddComponentWithProperties("base4.defaultHost", typeof(Base4Host), properties);


Here we're passing all our additional parameters as a Dictionary<string, object> inside our IDictionary of additional properties....  this isn't the most elegant implementation, but this is all code internal to a single facility so it's not really important to me... and it gets the job done just fine.


posted @ Thursday, October 19, 2006 9:46:17 AM (New Zealand Daylight Time, UTC+13:00)    Comments [2] | |
# Tuesday, October 17, 2006

Abstractions...  mmmm... so sweet

...a post from Ayende on abstractions, and specifically a mention of the logging "abstraction" in Castle... it's an interesting thing, for the Seismic product I worked logging (via the same abstraction) into a product a year or more ago...  in the end we needed the ability to log contextual information (basically exposing features already existing in log4net at the time, but not available via the Castle ILogger interface) and so I ended up creating a new interface that was a superset of the existing abstraction, IExtendedLogger...

here's the devil... looks simple...

public interface IExtendedLogger : ILogger

{

    void AddProperty(string key, object value);

    void RemoveProperty(string key);

}


However... because we're being a good little abstraction "whore" we end up with a few more classes to support this new interface, and make the user experience more pleasurable:



Though I was reasonably pleased with the end result a year ago, that was probably a couple of hours work + some more time tweaking (once you include the time to code up that test fixtures) that would've been better spent building additional functionality into the product.

I have to admit the lure of a needless abstraction is ever present to me... I enjoy halving a class into an abstract and concrete implementation, and then extracting an interface is like the candy coating... prefixing the concrete implementation with "Default" makes it even seem like you've all but got people lining up to create their own versions!  Wow, isn't it powerful, flexible.. and all sorts of other words ending in "ul" or "ile".

....But in the end, needless is needless - and I haven't needed the flexibility gained from this abstraction so far... after a year... a whole year, that's pretty much like never... sure I had grand plans, but they never did come to fruition... and grand plans don't keep me fed - YAGNI strikes again.

About the only thing I find the needless abstractions do is in clarifying my thinking on what I do and don't need, or more importantly what I do and don't want people to do with my code.... it let's me define just what I want my "pit of success" behavior to be, albeit not the implementation... Perhaps some of this stuff is better reserved for throw away prototypes then production code.

I think the best book I've found for discouraging this "80's guitar solo" of abstraction..um...ism is the Framework Design Guidelines... Though these abstractions do make it easy for me to maintain and grow my code (and the orthogonality of the design is generally good) it comes at the price of other people having difficulty learning my API through experimentation, and I fail to create a progressive framework... which after reading the aforementioned book, is something we all wan't to do.

I guess the final question is, do you reverse an abstraction that isn't required after such a long time...?  Or do you just avoid making the same mistake twice and live with the abstraction, assuming it's not hurting too many people - Is it worth lumping it with the rest of the "broken windows" in a project, or is that a little too brash?

posted @ Tuesday, October 17, 2006 10:53:52 PM (New Zealand Daylight Time, UTC+13:00)    Comments [0] | |

Startable facility and hosting base4

Ivan's pretty keen :) last week he demonstrated hosting the base4 service in ASP.Net ... cool stuff.

Now here he has placed the implementation in the HttpApplication class, and as a quick observation this would be a good candidate for moving into it's own component... and as luck would have it, Castle has just the thing, via the Startable facility.

Startable... (and the implied, stoppable ;o)

Now the startable facility is a very simple beast, basically... you create a class, that implements this interface:

/// <summary>

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

/// </summary>

public interface IStartable

{

    void Start();

    void Stop();

}


Which lives in the Castle.Core assembly... though the facility itself lives in the Castle.MicroKernel assembly... you should already have references to both, otherwise I doubt your container is working at all :P

And you then register the startable facility in the container:

<facility id="startable.facility"

    type="Castle.Facilities.Startable.StartableFacility, Castle.MicroKernel" />


And thats it... now whenever you register a component in the container, the startable facility will check it, and if it's found to implement IStartable it will add it to a list of components "awaiting startup"... once any of these awaiting components has had all it's dependencies satisfied it will be started (so it may be started as soon as the component is registered, if it doesn't have any dependencies - this will be the case for our component)...

Disposing of the container will cause the components to be stopped in turn... perfect for hosting our base4 server...

Reworking the hosting code to be a startable component...

...so taking what Ivan's done, we could rework it a little... and be able to host base4 in web apps, as well as say your business logic's test harness... here's my quick 'n dirty reworked implementation as a component that I did this afternoon... my final version probably won't have any dependencies on the HttpContext as I'll just rely on explicit declaration of all the settings as parameters in the container configuration... I tend to like keeping all the config in the container, one place to look 'n all that.

public class Base4Host : IStartable

{

    private const string _machineName = "localhost";       

    private const string _provider = "SQL2005";

    private string _appName;       

    private int _port;

    private string _root;

    private ServerConfiguration _configuration;

    private IServerProxy _proxy;

 

    public ServerConfiguration Configuration

    {

        get { return _configuration; }

    }

 

    public IServerProxy ServerProxy

    {

        get { return _proxy; }

    }

 

    public Base4Host(string appName, int port)

    {

        if (string.IsNullOrEmpty(appName)) throw new ArgumentNullException("appName");

        if (port <= 1024) throw new ArgumentOutOfRangeException("port", "port should be greater then 1024");

        _appName = appName;

        _port = port;

    }

 

    public Base4Host(string appName, int port, string root)

        : this(appName, port)

    {

        if (string.IsNullOrEmpty(root)) throw new ArgumentNullException("root");           

        _root = root;

    }

 

    #region IStartable Members

 

    public void Start()

    {

        _configuration = CreateConfiguration();      

        _proxy = ServerFactory.StartServer(_configuration, false);

        string base4Context = string.Format("tcp://Server:@localhost:{0}/{1}", _port, _appName);

        StorageContext.SetDefault(base4Context);           

    }

 

    public void Stop()

    {

        _proxy.Stop();

        _proxy = null;

        _configuration = null;

    }

 

    #endregion

 

    #region Support methods

 

    private ServerConfiguration CreateConfiguration()

    {

        ServerConfiguration configuration = new ServerConfiguration();

 

        DiscoverApplicationName();

        InsertApplicationRoot(configuration);

        InsertConnectionStrings(configuration);

        InsertConnectivityInformation(configuration);

 

        if (!Directory.Exists(configuration.Store.Root))

        {

            Directory.CreateDirectory(configuration.Store.Root);

        }

 

        return configuration;

    }

 

    private void InsertConnectivityInformation(ServerConfiguration configuration)

    {

        configuration.Store.Name = _appName;

        configuration.Store.Provider = _provider;

        configuration.Store.Port = _port;

        configuration.Store.MachineName = _machineName;

    }

 

    private void DiscoverApplicationName()

    {

        if (string.IsNullOrEmpty(_appName))

        {

            if (HttpContext.Current.Application["AppName"] == null)

            {

                Assembly assembly = Assembly.GetCallingAssembly();

                HttpContext.Current.Application["AppName"] = (AssemblyTitleAttribute.GetCustomAttribute(assembly, typeof(AssemblyTitleAttribute)) as AssemblyTitleAttribute).Title;

            }

 

            _appName = HttpContext.Current.Application["AppName"].ToString();

        }

    }

 

    private void InsertApplicationRoot(ServerConfiguration configuration)

    {

        string root = string.IsNullOrEmpty(_root) ? HttpContext.Current.Server.MapPath("~/") : _root;

        configuration.Store.Root = root.EndsWith("\\") ? root + "App_Data\\Base4" : root + "\\App_Data\\Base4";

    }

 

    private void InsertConnectionStrings(ServerConfiguration configuration)

    {

        string connectionStringName = ConfigurationManager.AppSettings["DefaultConnection"];

 

        if (string.IsNullOrEmpty(connectionStringName) && ConfigurationManager.ConnectionStrings != null

            && ConfigurationManager.ConnectionStrings.Count > 0)

        {

            connectionStringName = ConfigurationManager.ConnectionStrings[0].Name;

        }

 

        configuration.Store.ConnectionString = string.IsNullOrEmpty(connectionStringName) ? ConfigurationManager.AppSettings["Store.ConnectionString"] :

            ConfigurationManager.ConnectionStrings[connectionStringName].ConnectionString;

 

        SqlConnectionStringBuilder connStrBuilder = new SqlConnectionStringBuilder(configuration.Store.ConnectionString);

 

        connStrBuilder.InitialCatalog = "master";

        configuration.MasterConnectionString = connStrBuilder.ToString();

    }

 

    #endregion

}


Notice we don't expose a default constructor... how can the container create it?

Well, it can't unless we supply the parameters it requires... which is just what we'll do:

<component

    id="base4host.default"

    type="MyProject.Base4Host, MyProject">

    <parameters>

        <appName>GoatsAndBoats</appName>

        <port>11888</port>

    </parameters>           

</component>


Simple... a couple of useful extensions to our existing base4 facility may well be to:
  • Ensure the startable facility is installed... so we can fail-early and with a meaningful error during application startup.
  • Add some additional "optional" parameters for configuring the facility, so that it can take care of registering the Base4Host for us.

For the optional parameters, I'm thinking of doing something like this:

<facility id="base4.storageFacility"

    type="SomeProject.Core.Base4StorageFacility, SomeProject.Core"

    host="true"

    appName="GoatsAndBoats"

    port="11888"

    connectionString="local"

    />


At which point it's trivial to shift between accessing base4.net as a remote service vs. hosting it in your own app... unlike the remote setup you can skip providing the base4 url (context string) as it'll be implied from the app name and port.
.Net | base4 | castle
posted @ Tuesday, October 17, 2006 1:28:44 PM (New Zealand Daylight Time, UTC+13:00)    Comments [1] | |
# Monday, October 16, 2006

Monorail Pagination with Base4.Net

So, part of today was spent building "digg" style pagination for data I'm pulling out of base4... if you don't use digg, then what I mean is stuff like this:



Flickr and plenty of other sites use the same layout... and it does seem quite a convenient way to work your way through large result sets...

Fairly standard stuff, because I'm using monorail my first pit stop was the pagination helper - however there's a bit of an impedance mismatch here, as the pagination helper is geared towards paging through an IList containing all the records, where as generally speaking you're working with IItemList<T> and wanting to make use of the inherent paging support in base4.net... hmmm... at any rate, this isn't exactly "brilliant" code - but it might prove useful if you messing around with Monorail at home - something I think you should do.

Paging and base4.net

So, first off, I built a small class to represent a "page" from a larger set of query results in my application... it looks like this...

/// <summary>

/// Represents a page from a query

/// </summary>

/// <typeparam name="T"></typeparam>

public class PagedItemList<T> : IEnumerable<T>

    where T: class, IItem

{

    private IItemList<T> _items;              

    private int _pageNumber;

    private int _pageSize;

    private int _totalCount;

 

    public PagedItemList(IItemList<T> items, int pageSize, int pageNumber, int totalCount)

    {

        if (items == null) throw new ArgumentNullException("items");

        if (pageNumber <= 0) throw new ArgumentOutOfRangeException("pageNumber", "pageNumber must be greater then 0");

        if (pageSize <= 0) throw new ArgumentOutOfRangeException("pageSize", "pageSize must be greater then 0");

        if (totalCount < 0) throw new ArgumentOutOfRangeException("totalCount", "totalCount must be greater then or equal to 0");

 

        _items = items;

        _pageNumber = pageNumber;

        _pageSize = pageSize;

        _totalCount = totalCount;                               

    }

 

    /// <summary>

    /// The count of items on this page

    /// </summary>

    public int PageCount

    {

        get { return (int)Math.Ceiling(((double)TotalCount) / ((double)PageSize)); }

    }

 

    /// <summary>

    /// Index of the first item on this page

    /// </summary>

    public int FirstItemIndex

    {

        get

        {

            return PageSize * (PageNumber-1);

        }

    }

 

    /// <summary>

    /// Index of the last item on this page

    /// </summary>

    public int LastItemIndex

    {

        get

        {

            return Math.Min(FirstItemIndex + (PageSize - 1), TotalCount - 1);

        }

    }

 

    /// <summary>

    /// 1-relative page number index

    /// </summary>

    public int PageNumber

    {

        get

        {

            return _pageNumber;

        }

    }

 

    /// <summary>

    /// The size of each page

    /// </summary>

    public int PageSize

    {

        get { return _pageSize; }

    }

 

    /// <summary>

    /// Total number of results returned from the query

    /// </summary>

    public int TotalCount

    {

        get { return _totalCount; }

    }

 

    /// <summary>

    /// Number of items on this page

    /// </summary>

    public int Count

    {

        get { return _items.Count; }

    }

 

    /// <summary>

    /// the underlying list of items

    /// </summary>

    public IItemList<T> Items

    {

        get { return _items; }

    }

 

    public IEnumerator<T> GetEnumerator()

    {

        return _items.GetEnumerator();

    }

 

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()

    {

        return ((IEnumerable)_items).GetEnumerator();

    }

}


Pretty mundane, next we just extend my existing repository with a new method for returning a PagedItemList<T>... here's how it looks:

public virtual PagedItemList<T> Find(ObjectQuery query, int pageSize, int pageNumber)

{           

    if (query == null) throw new ArgumentNullException("query");

    if (pageSize <= 0) throw new ArgumentException("pageSize must be greater then 0");

    if (pageNumber <= 0) throw new ArgumentException("pageNumber must be greater then 0");

 

    int count = Convert.ToInt32(_context.ExecuteScalar(query.Compile().SELECT_COUNT()));

 

    query.Path.PageSize = pageSize;

    query.Path.PageNumber = pageNumber;

 

    return new PagedItemList<T>(Find(query), pageSize, pageNumber, count);

}


For our query we first estabilsh the total count of results, then we just run the query again and return the results for the selected page.

From Base4.Net to Monorail

Now, our PagedItemList<T> is useful by itself, but there's a more feature-complete interface in monorail for representing a "page" of informaton for display logic, used by the pagination helper, it's called IPaginatedPage.

public interface IPaginatedPage : IEnumerable

{

    int CurrentIndex { get; }   

    int LastIndex { get; }   

    int NextIndex { get; }   

    int PreviousIndex { get; }   

    int FirstIndex { get; }

    int FirstItem { get; }

    int LastItem { get; }

    int TotalItems { get; }

    bool HasPrevious { get; }   

    bool HasNext { get; }

    bool HasFirst { get; }

    bool HasLast { get; }

}


...so, we just build a little adaptor object, using the abstract base page that implementes IPaginatedPage, called "AbstractPage" funnily enough - here I've called my adaptor Base4Page.

public class Base4Page<T> : AbstractPage

    where T: class, IItem

{

    private PagedItemList<T> _items;

 

    public Base4Page(PagedItemList<T> items)

    {

        if (items == null) throw new ArgumentNullException("items");

        _items = items;

 

        CalculatePaginationInfo(items.FirstItemIndex, items.LastItemIndex, items.TotalCount, items.PageSize, items.PageNumber);

    }

 

    public override System.Collections.IEnumerator GetEnumerator()

    {

        return _items.GetEnumerator();

    }

}


Soo... last of all, where's the pay off?

Well, first thing's first, now you can do this in your controller:

public void Users(int pageSize, int page)

{           

    ObjectQuery query = new ObjectQuery(typeof(Car));
    // not enough set some further critiera...

    PropertyBag.Add("Cars", new Base4Page<Car>(_carRepository.Find(query, pageSize, page)));

}


At which point, you could do some simple pagination in your views (and pagination examples for existing Monorail websites can be cut 'n' pasted in to give you a head start)...

<table cellpadding="4">
<tr>
<th>Make</th>
<th>Model</th>
<th>Year</th>
</tr>
#foreach($Car in $Cars)
<tr>
<td>$!Car.Make</td>
<td>$!Car.Model</td>
<td>$!Car.Year</td>
</tr>
#end
</table>
<div class="pagination" id="pagination">
<table width="90%" border="0">
<tr>
<td>Showing $Cars.FirstItem - $Cars.LastItem of $Cars.TotalItems</td>
<td align="right">
#if($Cars.HasFirst) $PaginationHelper.CreatePageLink( 1, "first", null, null) ) #end
#if(!$Cars.HasFirst) first #end
#if($Cars.HasPrevious) | $PaginationHelper.CreatePageLink( $Cars.PreviousIndex, "prev", null, null) ) #end
#if(!$Cars.HasPrevious) | prev #end
#if($Cars.HasNext) | $PaginationHelper.CreatePageLink( $Cars.NextIndex, "next",null, null) ) #end
#if(!$Cars.HasNext) | next #end
#if($Cars.HasLast) | $PaginationHelper.CreatePageLink( $Cars.LastIndex, "last",null, null) ) #end
#if(!$Cars.HasLast) | last #end
</td>
</tr>
</table>
</div>

And of course it's not much harder to write the logic for displaying "digg" style pagination.... I decided to write it as a helper in C#, because after messing with it for 15 minutes in brail it pissed me off too much (some things in brail are quite annoying compared to normal boo, for instance I couldn't seem to use the "range(...)" builtin, and if your view doesn't have any content after the last <% ... %> block it throws up a compile time exception... Admittedly I haven't done a get latest from the Castle site in a couple of weeks... so this might not actually be a problem any more, or maybe I just don't have the brail engine configure "just right".

public abstract class AbstractDiggPaginationHelper : AbstractHelper

{

    public string CreateDiggPagination(IPaginatedPage page, int adjacents)

    {

        return CreateDiggPagination(page, adjacents, null);

    }

 

    public string CreateDiggPagination(IPaginatedPage page, int adjacents, IDictionary queryStringParams)

    {

        StringBuilder output = new StringBuilder();

        WriteLink(output, page.PreviousIndex, "« prev", !page.HasPrevious, queryStringParams);

 

        if (page.LastIndex < (4 + (adjacents * 2))) // not enough links to make it worth breaking up

        {

            WriteNumberedLinks(output, page, 1, page.LastIndex, queryStringParams);

        }

        else

        {               

            if ((page.LastIndex - (adjacents * 2) > page.CurrentIndex) && // in the middle

                    (page.CurrentIndex > (adjacents * 2)))

            {

                WriteNumberedLinks(output, page, 1, 2, queryStringParams);

                WriteElipsis(output);

                WriteNumberedLinks(output, page, page.CurrentIndex - adjacents, page.CurrentIndex + adjacents, queryStringParams);

                WriteElipsis(output);

                WriteNumberedLinks(output, page, page.LastIndex - 1, page.LastIndex, queryStringParams);

            }

            else if (page.CurrentIndex < (page.LastIndex /2))

            {

                WriteNumberedLinks(output, page, 1, 2 + (adjacents * 2), queryStringParams);

                WriteElipsis(output);

                WriteNumberedLinks(output, page, page.LastIndex - 1, page.LastIndex, queryStringParams);

            }               

            else // at the end

            {

                WriteNumberedLinks(output, page, 1, 2, queryStringParams);                   

                WriteElipsis(output);

                WriteNumberedLinks(output, page, page.LastIndex - (2 + (adjacents * 2)), page.LastIndex, queryStringParams);

            }

        }

 

        WriteLink(output, page.NextIndex, "next »", !page.HasNext, queryStringParams);

        return output.ToString();

    }

 

    private void WriteElipsis(StringBuilder builder)

    {

        builder.Append("...");           

    }

 

    private void WriteNumberedLinks(StringBuilder builder, IPaginatedPage page, int startIndex, int endIndex, IDictionary queryStringParams)

    {           

        for (int i=startIndex; i<= endIndex; i++)

        {

            WriteNumberedLink(builder, page, i, queryStringParams);

        }

    }

 

    private void WriteLink(StringBuilder builder, int index, string text, bool disabled, IDictionary queryStringParams)

    {

        if (disabled)

        {

            builder.AppendFormat("<span class=\"disabled\">{0}</span>", text);

        }

        else

        {

            WritePageLink(builder, index, text, null, queryStringParams);

        }

    }

 

    private void WriteNumberedLink(StringBuilder builder, IPaginatedPage page, int index, IDictionary queryStringParams)

    {

        if (index == page.CurrentIndex)

        {

            builder.AppendFormat("<span class=\"current\">{0}</span>", index);

        }

        else

        {

            WritePageLink(builder, index, index.ToString(), null, queryStringParams);

        }

    }

 

    protected abstract void WritePageLink(StringBuilder builder, int page, String text, IDictionary htmlAttributes, IDictionary queryStringParams);

 

}


The guts of the helper is in an abstract class, simply so I could test the numbering logic without having to worry about creating a controller & http context (just implement the WritePageLink method with some simple text output ... the implementation is here:

public class DiggPaginationHelper : AbstractDiggPaginationHelper

{

 

    protected override void WritePageLink(StringBuilder builder, int page, String text, IDictionary htmlAttributes, IDictionary queryStringParams)

    {

        string filePath = "";

 

        if (CurrentContext != null)

        {

            filePath = CurrentContext.Request.FilePath;

        }

 

        if (queryStringParams == null)

        {

            queryStringParams = new Hashtable();

        }

 

        queryStringParams["page"] = page.ToString();

 

        builder.AppendFormat("<a href=\"{0}?{1}\" {2}>{3}</a>", filePath, BuildQueryString(queryStringParams), GetAttributes(htmlAttributes), text);

    }

}


At which point you can just register it on the controller, and call it with something like ${DiggPaginationHelper.CreateDiggPagination(tracks, 3)} and get yourself a nice little paging display.  The second parameter is the "adjacent" - which can be used to control how many pages are displayed either side of the selected page when dealing with lots of results.

Oh, and of course you might want some CSS to go with it...

/* pagination */

 

div.pagination {

    padding: 3px;

    margin: 3px;

}

 

div.pagination a {

    color: #000099;

    text-decoration: none;   

    padding: 2px 5px 2px 5px;

    margin: 2px;

    border: 1px solid #AAAFEE;   

}

 

div.pagination a:hover, div.pagination a:active {

    color: #000;

    border: 1px solid #000099;   

}

 

div.pagination span.current {   

    font-weight: bold;

    background-color: #000099;

    color: #FFF;

    padding: 2px 5px 2px 5px;

    margin: 2px;

    border: 1px solid #000099;

}

 

div.pagination span.disabled {

    color: #DDD;

    padding: 2px 5px 2px 5px;

    margin: 2px;

    border: 1px solid #EEE;   

}



.Net | base4 | castle
posted @ Monday, October 16, 2006 5:40:14 PM (New Zealand Daylight Time, UTC+13:00)    Comments [2] | |
# Wednesday, October 11, 2006

Base4 & Castle

Well I've been working with HTML & style sheets today (mostly) - It's be a long while since I've done web development, so it was a little tedious, and it did briefly cross my mind that life might be easier if we lived in some kind of dictatorship where style sheets and layout were provided for me by the "man"... at any rate I also managed to fit in a bit of monorail and base4 to keep my brain from freezing over.

I think for this post I might just talk about the way I'm using base4... basically I prototyped some stuff and came to the conclusion that I didn't like the smell of the static StorageContext class in base4 and it's default connection - too hard to test against - not to say that it's a bad idea, just that I couldn't see any easy way to test and mock code  for code that used/consumed it... so I decided to work up a simple alternative using castle's IoC and some generic interfaces...

At this point... If you've been using Castle for more then a couple of week this is all old news I'm sure, so probably better off finding something else to read ;o)

The facility

First off we have a facility:

public class Base4StorageFacility : AbstractFacility

{

    protected override void Init()

    {

        string url = FacilityConfig.Attributes["url"];

        if (string.IsNullOrEmpty(url))

        {

            throw new StorageException("The Base4StorageFacility requires a \"url\" attribute to be set");

        }

 

        Kernel.AddComponentInstance("base4.defaultContext", typeof (IItemContext), StorageContext.NewContext(url));

        Kernel.AddComponent("base4.repository", typeof (IRepository<>), typeof (Base4Repository<>));

    }

}


A facility extends the container with additional functionality, in this case the only reason we're using a facility (instead of registering the components themselves individually) is because we're using a static method to create our context for a specific base4 connection url.

Moving on from here we can register the facility in the containers configuration, incidentally now I have somewhere pleasant to configure what base4 server I connect to by default in my application.

<facility id="base4.storageFacility"

    type="MyProject.Core.Base4StorageFacility, MyProject.Core"

    url="tcp://Server:@localhost:999/Base4_default" />


The Repository

Now what about the IRepository<> ? well here's the interface:

public interface IRepository<T>

    where T : class, IItem, new()

{

    IItemListProxy<T> List();

    IItemList<T> FindAll();

    IItemList<T> Find(ObjectQuery query);

    IItemList<T> Find(string path);

    IItemList<T> Find(string path, params string[] replaces);

    IItemList<T> Find(ObjectPath path);

    IItemList<T> Find(ObjectPath path, ObjectScope scope);

    IItemList<T> FindUsingSQL(string SQL);

    IItemList<T> FindUsingSQL(string SQL, ObjectScope scope);

    T Get(T previous);

    T Get(object id);

    T Get(ItemKey<T> key);

    T Get(string relativeUri);

    T FindOne(ObjectQuery query);

    T FindOne(string opath);

    T FindOne(string path, params string[] replaces);

    T FindOne(ObjectPath path);

    T FindOneUsingSQL(string SQL);

    T FindOneUsingSQL(string SQL, ObjectScope scope);

    T FindOne(string opath, ObjectScope scope);

    T FindOne(ObjectPath path, ObjectScope scope);

    void DeleteAll();

    void Delete(ObjectPath path);

    void Delete(string path);

    void Delete(string path, params string[] replaces);

    void Delete(T item);

    void Save(T item);

    T Create(string Xml);

    T Create(XmlReader reader);

    T Create();

}


It's pretty much works like IItemContext, except that you avoid having to pass generic parameters to the individual methods because the interface itself has a generic parameter... there's a couple of extras there that I'll cover at the end of this post too.

Conversely, the class Base4Repository<T> implements this interface... which looks like this (or at least the first few methods, I've left the rest out for brevity) - this is similar to what Ivan has done.

public class Base4Repository<T> : IRepository<T>

    where T : class, IItem, new()

{

    private IItemContext _context;

 

    public Base4Repository(IItemContext context)

    {

        if (context == null) throw new ArgumentNullException("context");

        _context = context;

    }

 

    public virtual IItemListProxy<T> List()

    {

        return _context.List<T>();

    }

 

    public virtual IItemList<T> FindAll()

    {

        return _context.FindAll<T>();

    }


Notice that it doesn't have a parameterless constructor, we rely on the container to inject the default IItemContext when creating instances of the Base4Repository...

The Container

Now, by default the container assumes a component has a "singleton" lifestyle, thankfully for a type with a generic parameter it is per that parameter, so this test case below passes - incidentally if you tend to use lifecycles other then the default, I would strongly suggest adding tests to make sure the lifecycle is actually applied... you can just imagine what happens in a multi-threaded app when a "Message" class has a singleton lifecycle when you expected a transient ;o) you end up with some bizarre behavior that might not be picked up in normal unit tests.

[Test]

public void IsSingleton()

{

    IRepository<FileBase> fileRepository1 = container.Resolve<IRepository<FileBase>>();

    IRepository<FileBase> fileRepository2 = container.Resolve<IRepository<FileBase>>();

    Assert.AreSame(fileRepository1, fileRepository2);

 

    IRepository<TypeImpl> typeRepository1 = container.Resolve<IRepository<TypeImpl>>();

    IRepository<TypeImpl> typeRepository2 = container.Resolve<IRepository<TypeImpl>>();

    Assert.AreSame(typeRepository1, typeRepository2);

}


cool, clear as mud?

Right... so moving on from there, in my own components when I need to access data I now use the repository... so I could, for instance, create a monorail controller like this:

public class FileController : BaseController

{

    private IRepository<FileBase> _repository;

 

    public FileController(IRepository<FileBase> repository)

    {

        if (repository == null) throw new ArgumentNullException("repository");

        _repository = repository;

    }

 

    public void Fetch(Guid fileId)

    {

        CancelLayout();

        CancelView(); // very important

        Response.Clear(); // ensure the response is empty

 

        FileBase file = _repository.Get(fileId);

        if (file != null)

        {               

            Response.ContentType = file.MimeType;

            file.FileContent.CopyTo(Response.OutputStream);

        }

        else

        {               

            Response.StatusCode = 404;

        }

    }       

}


And everything will just work - now in some cases this isn't convenient (the dependency injection model) so I broke down and created a static repository class as well, which accesses the default container for the application... basically it has the same interface as IRepository, but they're static methods.. so you can code like this:

Track track = Repository<Track>.Get(id);


Personally I'm not actually that keen on this approach - The Syzmk RMP product I've worked on uses the container everywhere, but avoids ever having to access the default container statically...  and if you end up with a class being injected with a large number of dependencies it's often (but not always) a good indication that there's some violation of orthogonality - if only because a class consuming that many dependencies is probably doing more then one thing... a little difficult to pick up on otherwise.

But at any rate It seems pretty good for a website, where I can't see me using more the one container (or even child containers) within the same app domain.

Wrinkles...

Moving beyond that, the last thing I have to say is that originally I was creating new instances and then saving them with a repository like this:

Group group = new Group();

...
Repository<Group>.Save(group);

... 

User user = new User();

...
user.Groups.Add(group);

...
Repository<User>.Save(user);


However, it all turns to 4 shades of brown when we go to add to a many-to-many collection, like this:

Goat goat = new Goat();

goat.Name = "junk";

Repository<Goat>.Save(goat);

 

BoatOfGoats boat = new BoatOfGoats();

boat.Name = "track";

boat.Goats.Add(goat); // <-- "StorageException : Default is not available, as no default has been set"

Repository<BoatOfGoats>.Save(track);


As far as I can tell the event handling for the Add(item) method expects a default context to be assigned... now I'd be tempted to call this a bug, but that's a bit rash till I understand the in's and out's of base4, however there's an easy way round it... and that's to assign the context yourself :) so a fix would be to add this line before the one that bombs:

track.Context = container.Resolve<IItemContext>();


But that's pretty kludgey, so instead of using:

Goat goat = new Goat();


I added some Create(...) overloads to the repository to take care of it... and do this:

Genre genre = Repository<Genre>.Create();

Last of all, though I haven't drawn on the entire implementation, I'm hoping to follow (At least in spirit) some of the work Ayende has done with his NHibernate repository concept as the project progresses, I think it will add a more natural "feel" combined with the repositories for implementing transactions vs. interacting with base4's ObjectTransaction directly, not to mention providing something I can test and mock out easily...  We shall see what actually happens as the project progresses.



.Net | base4 | castle
posted @ Wednesday, October 11, 2006 8:34:54 PM (New Zealand Daylight Time, UTC+13:00)    Comments [3] | |
Search
FeedCount

Tags...
.Net (83) .Net Reactor (4) .net user groups (9) 2008SummerRoadTrip (1) ActiveRecord (1) architecture (1) architecture chat (95) ArchitectureCamp2007 (2) asp.net (1) Astoria (1) Auckland (1) base4 (9) batching (1) binsor (1) blog (4) boo (1) books (1) C# 3.0 (9) cambodia (9) CAML.Net (1) castle (40) china (8) codecamp (3) codeplex (3) dapper.net (1) DevDefined Ltd. (4) DirectShow.Net (1) DLR (1) DSL (4) EAUG (1) Enterprise Architect (5) Enterprise Architecture (1) Enterprise Library (1) F# (1) feedburner (2) first post (1) Friendster (1) generics (1) googlegears (1) hacks (3) hardware (3) hongkong (2) Horn (1) hyper-v (1) ideas (1) IoC (21) IronPython (13) IronRuby (2) jobs (1) Languages (2) laos (8) LINQ (7) LiveId (1) LLU (1) Local Government (1) MDA (1) MDD (1) microsoft (1) Model Driven Development (1) mono (1) monorail (2) Movies (1) Music (1) nDepend (1) news (1) NHibernate (3) NUnit (2) nvelocity (1) OAuth (6) office (1) OpenSocial (1) orcon (1) photos (1) php (1) PostSharp (1) powerpoint (1) presentations (1) ReSharper (1) REST (2) rhino commons (3) rhinomocks (5) Ruby (1) SaaS (1) scm (1) Screen Architect (0) SharePoint (5) silverlight (1) Splicer (4) SQL2008 (1) supcom (1) survey (1) svn (1) Syzmk (4) thailand (6) Tools (2) Tortoise SVN (1) trac (2) Travel (36) Unity (2) vietnam (7) vista (2) visual nhibernate (1) vmware (1) volta (3) VS2008 (1) WCF (3) wiki (2) wikipedia (1) Windows Server 2008 (1) windsor (6) WinForms (1) wix (2) WPF (2) xmlrpc (1) yahoo pipes (1)
Who am I?
Alex Henderson
Alex Henderson
Auckland, New Zealand
Managing Director at Dev|Defined Limited

"Self Confessed Coding Junky for 15 years"
View Alex Henderson's profile on LinkedIn
 
Mobile: +64-21-402-969
Email: bittercoder 'at' gmail 'dot' com
MSN: bittercoder_nz@hotmail
Skype: alex.devdefined
Navigation