One of Castle Windsor's facilities addresses wiring up of WCF services. So far, the sparse documentation for the WCF Facility seems to indicate that you have to configure your container in a global.asax. That's not much to my liking. First of all, it reeks of ASP.NET, and secondly, it's not going to work if you expose WCF over protocols other than HTTP.

However, now that we know that a custom ServiceHostFactory is effectively a Singleton, a much better alternative is to derive from the WCF Facility's DefaultServiceHost class:

public class FooServiceHostFactory : 
    DefaultServiceHostFactory
{
    public FooServiceHostFactory()
        : base(FooServiceHostFactory.CreateKernel())
    {
    }
 
    private static IKernel CreateKernel()
    {
        var container = new WindsorContainer();
 
        container.AddFacility<WcfFacility>();
 
        container.Register(Component
            .For<FooService>()
            .LifeStyle.Transient);
        container.Register(Component
            .For<IBar>()
            .ImplementedBy<Bar>());
 
        return container.Kernel;
    }
}

Although it feels a little odd to create a container and then not really use it, but only its Kernel property, this works like a charm. It correctly wires up this FooService:

public class FooService : IFooService
{
    private readonly IBar bar;
 
    public FooService(IBar bar)
    {
        if (bar == null)
        {
            throw new ArgumentNullException("bar");
        }
 
        this.bar = bar;
    }
 
    #region IFooService Members
 
    public string Foo()
    {
        return this.bar.Baz;
    }
 
    #endregion
}

However, instead of the static CreateKernel method that creates the IKernel instance, I suggest that the WCF Facility utilizes the Factory Method pattern. As the WCF Facility has not yet been released, perhaps there's still time for that change.

In any case, the WCF Facility saves you from writing a lot of infrastructure code if you would like to wire your WCF services with Castle Windsor.


Comments

There's a plan to provide Facility's base ServiceHostFactory that you could use out of the box with very minimal anmount if XML config in your web.config/app.config file:

<installers>
<install assembly="Ploeh.AssemblyContainingWindsorInstallers"/>
</ installers>

See http://stw.castleproject.org/Windsor.Registering-Installers.ashx

Alternatively you could override protected IWindsorInstaller GetInstallers(); method and configure the container entirely in code.

Thoughts?
2010-05-18 08:24 UTC
That would definitely address most cases, including the one I'm currently looking at, although I'm not sure I understand your last sentence. Did you mean that I can implement a custom IWindsorInstaller? If so, that makes a lot of sense.

For the edge cases where adding an Installer isn't enough, I'd still prefer a Factory Method hook in DefaultServiceHostFactory, but being able to specify an Installer in web.config will likely address 90 percent (or more) of scenarios.

Looks good!
2010-05-18 08:38 UTC
In both cases you will need to provide your own implementation of IWindsorInstaller that will provide services and configuration to the container. The difference between the two approaches is as follows:

If you use Facility's default SH Factory it will look into your web.config for informations about how to configure itself.
ALternativelty you can provide your own subclass of the SH Factory, override its protected IWindsorInstaller[] GetInstallers(); method and then you'll be able to configure the container without using config file.
2010-05-18 08:45 UTC
Why would you prefer factory method instead of just pointing to installers? What do you need to do that the other approach can't address?
2010-05-18 08:47 UTC
Thanks for your explanation. I think that sounds very promising. As far as I can tell, this is still in the future, right? I don't see any GetInstallers() on DefaultServiceHostFactory right now (based on the code I downloaded and compiled last week).

Don't get me wrong on the Factory Method thing. I don't expect to need it often (if at all), but I just think it would be a good OCP thing to do... Off the top of my head, I can't remember whether there are things you can do to a container that you can't do from an Installer. Maybe there aren't...
2010-05-18 09:05 UTC
you're right, GetInstallers() is not there yet, (same as specifying installers in xml is part of trunk, not v2.1).

I do intend to leave the door open with factory method for people who can't use xml even if it's so minimal (or feel sick when even thinking about xml), but as you said - there really isn't anything you couldn't do from installer so I imagine it would be for emergency cases only.
2010-05-18 09:15 UTC


Wish to comment?

You can add a comment to this post by sending me a pull request. Alternatively, you can discuss this post on Twitter or Google Plus, or somewhere else with a permalink. Ping me with the link, and I may add it as a comment.

Published

Tuesday, 18 May 2010 05:27:56 UTC

Tags



"Our team wholeheartedly endorses Mark. His expert service provides tremendous value."
Hire me!