Showing posts with label castle. Show all posts
Showing posts with label castle. Show all posts

Wednesday, November 17, 2010

Windsor-managed MembershipProviders

I see many questions on Stackoverflow that are basically variants of this: "How can I integrate my custom MembershipProvider into my IoC container?"

Integrating your custom MembershipProvider to a IoC container has many advantages, since it would let you treat it just like any other service: you could manage its lifetime, dependencies, configuration, even proxy it if you wanted.

Problem is, MembershipProviders are one of those things that are managed by the ASP.NET runtime. You just configure it in your web.config and the runtime instantiates it when it's needed. You don't really get much control over its creation.

A cheap solution is to use the container as a service locator directly in your membership provider (using something like CommonServiceLocator), e.g.:

public class MyMembershipProvider : MembershipProvider {
    private IUserRepository repo {
        get { return ServiceLocator.Current.GetInstance<IUserRepository>(); }
    }

    public override string GetUserNameByEmail(string email) {
        return repo.First(u => u.Email == email);
    }

    ...
}

Using a service locator like this should be avoided as much as possible. Mark Seeman explains it thoroughly in this article. In a nutshell, you want to limit the usage of the service locator pattern to glue code (i.e. very low-level infrastracture), even there use it as little as possible, and never use it in application-level code.

As usual with this kind of problems, the solution is to write a wrapper/adapter/bridge/whatever-you-want-to-call-it that isolates the issue so that client code doesn't have to suffer it. It's similar in concept to the implementation of Windsor-managed HttpModules. It's actually simpler than that, we don't need a custom lifestyle manager here.

In fact, Spring.NET has had such an adapter for quite some time. The only problem with that implementation is that you can't change the lifetime of the custom provider, it's always a singleton. My implementation doesn't have this limitation: your provider can be transient, singleton, per web request, whatever. The price for this is that you can't use Initialize() (more precisely, it won't do anything), but since it's managed by the container, you can use the container to provide any configuration, which is much more flexible. The implementation is about 200 lines of boring, simple code so I'm not going to post it here. It does use Windsor as a service locator, but this is low-level infrastracture/glue code. The goal here is to keep your code clean.

The code is here, and here's how to use it:

  1. Write your custom MembershipProvider as a regular component, using constructor or property injection as you see fit.
  2. Implement IContainerAccessor in your global HttpApplication class. Use this article as reference.
  3. Register your custom provider in Windsor and assign a name to the component. E.g.:

    container.Register(Component.For<MyMembershipProvider>()
        .LifeStyle.Transient
        .Named("myProvider"));
  4. Register your custom provider in your web.config using the adapter and referencing the name of the corresponding Windsor component in a "providerId" attribute. E.g.:

        <membership defaultProvider="customProvider">
          <providers>
            <clear/>
            <add name="customProvider" type="ProviderInjection.WebWindsorMembershipProvider, ProviderInjection" providerId="myProvider"/>
          </providers>
        </membership>

That's it. Here's a sample app that you can use as reference. This can be easily ported to any IoC container, and for any provider like RoleProvider, ProfileProvider, etc. I haven't used this in anger so let me know if you have any problems with it.

Friday, June 25, 2010

Hybrid lifestyles in Windsor

All Inversion of Control (IoC) containers offer some way to control the lifecycle or scope of the component instances. Singleton (one instance per container) and Transient (a new instance each time your request it from the container) are the two most common scopes.

Castle Windsor calls these scopes "lifestyles" (the term "lifecycle" is used for something else) and it comes with these built-in lifestyles (I'll just quote the documentation):

  • Singleton (default): one instance per container
  • Transient: a new instance each time your request it from the container
  • PerThread: one instance per thread
  • PerWebRequest: one instance per HttpContext (HTTP request)
  • Pooled: instances will be pooled to avoid unnecessary constructions

More importantly, a custom lifestyle manager can be plugged-in, just by implementing the ILifestyleManager interface. Some examples of this are the WCF facility PerWcfSession and PerWcfOperation lifestyles and the PerHttpApplication lifestyle I implemented to inject dependencies to HttpModules.

There are other lifestyles that come in handy sometimes, especially in web applications. I created the Castle.Windsor.Lifestyles contrib project to host them. I have implemented these lifestyles so far:

  • Abstract hybrid lifestyle
  • Abstract hybrid PerWebRequest + X
  • Hybrid PerWebRequest + Transient
  • PerWebSession: one instance per HTTP session
  • PerHttpApplication (mentioned above)

An hybrid lifestyle is one that actually blends two underlying lifestyles: a main lifestyle and a secondary lifestyle. The hybrid lifestyle first tries to use the main lifestyle; if it's unavailable for some reason, it uses the secondary lifestyle. This is commonly used with PerWebRequest as the main lifestyle: if the HTTP context is available, it's used as the scope for the component instance; otherwise the secondary lifestyle is used.

The PerWebSession has a couple of caveats:

  • Components using this lifestyle have to be serializable if you're using a session-state mode other than InProc.
  • Components using this lifestyle will not be properly released, since the session end event only fires when using the InProc session-state mode.

Usage:

  1. Add a reference to Castle.Windsor.Lifestyles.dll
  2. Use the appropriate lifestyle descriptor in your registration, e.g.:

    container.Register(Component.For<SomeService>()

                    .LifeStyle.HybridPerWebRequestTransient());

Sunday, November 8, 2009

Windsor-managed HttpModules

Another interesting question from stackoverflow:

I have a custom HTTP Module. I would like to inject the logger using my IoC framework, so I can log errors in the module. However, of course I don't get a constructor, so can't inject it into that. What's the best way to go about this?

First thing we need to recognize is that there are actually two problems here:

  1. Taking control of IHttpModule instantiation in order to inject it services, and
  2. Managing the lifecycle of the IHttpModule

Let's start with the lifecycle. Ayende has the best summary of the lifecycle of HttpApplication and its related IHttpModules I've found. If you're not familiar with this, go read it now, I'll wait.

Back so soon? Ok, we can implement this in Windsor with a pluggable lifestyle. Lifestyle managers dictate when it's necessary to create a new instance of the component, but not how. They don't get to actually create the instance, that's the responsibility of the component activator. Here's the full component creation flow reference.

So we need to write a new lifestyle manager that allows at most one component instance per HttpApplication instance. I won't bother you with the implementation details since it's very similar to the per-request lifestyle: it's composed of the LifestyleManager itself and a HttpModule as a helper to store component instances.

Now we need a way to manage the IHttpModule instantiation. Unsurprisingly, we can do that with another IHttpModule, which I'll call WindsorHttpModule.
This WindsorHttpModule will be responsible for the initialization of the "user-level", Windsor-managed IHttpModules.

So, to summarize:

  1. Register PerHttpApplicationLifestyleModule and WindsorHttpModule:
    <httpModules>
        <add name="PerHttpApplicationLifestyleModule" type="HttpModuleInjection.PerHttpApplicationLifestyleModule, HttpModuleInjection"/>
        <add name="WindsorModule" type="HttpModuleInjection.WindsorHttpModule, HttpModuleInjection"/>
    </httpModules>
  2. Write your http modules using normal dependency injection style, e.g.:
    public class Service {
        public DateTime Now {
            get { return DateTime.Now; }
        }
    }
    
    public class UserHttpModule : IHttpModule {
        private readonly Service s;
    
        public UserHttpModule(Service s) {
            this.s = s;
        }
    
        public void Init(HttpApplication context) {
            context.BeginRequest += context_BeginRequest;
        }
    
        private void context_BeginRequest(object sender, EventArgs e) {
            var app = (HttpApplication) sender;
            app.Response.Write(s.Now);
        }
    
        public void Dispose() {}
    }
  3. Make your HttpApplication implement IContainerAccessor
  4. Register your http modules in Windsor, using the custom lifestyle:
    container.AddComponent<Service>();
    container.Register(Component.For<IHttpModule>()
                           .ImplementedBy<UserHttpModule>()
                           .LifeStyle.Custom<PerHttpApplicationLifestyleManager>());

    Note that UserHttpModule is not registered in the <httpModules> section of web.config, since it's managed by Windsor now.

You can also combine this with Rashid's BaseHttpModule to make your modules more testable.

Full source code is here.

Saturday, October 31, 2009

Visualizing Windsor components dependencies

When working with Windsor on complex applications, it's pretty common to have hundreds or even thousands of components managed by the container. The dependencies can get quite intricate and sometimes you need to see the big picture. Static analyzers like NDepend don't cut it since components are wired by Windsor at runtime.

So here's a little guide to output a PNG of a container's components and dependencies, using QuickGraph and GLEE.

First we need to model the components and dependencies as a regular Dictionary. The key of this dictionary will be a description of the component (a regular string) and the value of this dictionary will be a list of dependencies.

var container = new WindsorContainer();

// ...add components...

var dependencyDict = container.Kernel.GraphNodes
    .Distinct(new EqComparer<GraphNode>((a, b) => a.Describe() == b.Describe(), n => n.Describe().GetHashCode()))
    .ToDictionary(n => n.Describe(), n => n.Dependents.Select(a => a.Describe()));

EqComparer is just a functional IEqualityComparer. Distinct() is needed because when using forwarded types you'd get duplicate dictionary keys.

Now we dump this into a QuickGraph digraph:

var graph = dependencyDict.ToVertexAndEdgeListGraph(kv => kv.Value.Select(n => new SEquatableEdge<string>(kv.Key, n)));

and finally we render the digraph to a PNG using GLEE:

graph.ToGleeGraph().ToBitmap().Save("windsor.png");

Here's a sample output from SolrNet's inner components (click to zoom):

 windsor

 

Only problem with this is that it doesn't take custom subdependency resolvers (like an ArrayResolver) into account, since they can't be modeled in the kernel's GraphNodes.

Here's what it looks like after some ad-hoc fixes:

solrnet-full

Here's the full code.

Related articles:

 

Thursday, August 20, 2009

Poor man's profiler with Windsor

I generally advise to keep the IoC container out of the tests, but sometimes it is a convenient tool to have. Take for example the auto-mocking container concept. It's just too useful so I make an exception to the previous rule sometimes.

Here's another use for a container in a test: a profiler. All IoC containers have some proxying abilities (or rather, they delegate to one of the proxying libraries), which can be leveraged to build a basic profiler. A profiler is especially useful in integration tests where there's something that's taking too much time but you can't put your finger on the culprit simply because there are too many components involved.

A real-world example: an application which uses SolrNet was taking too long when getting lots of documents from Solr. There was nothing weird in Solr's log so it was a client issue. Let's profile it!

Setting up the profiler

We create a ProfilingContainer and add all the components we want to profile:

IWindsorContainer container = new ProfilingContainer(); 
container.AddComponent<ISolrDocumentResponseParser<Document>, SolrDocumentResponseParser<Document>>(); 
container.AddComponent<ISolrResponseParser<Document>, ResultsResponseParser<Document>>("resultsParser"); 
container.AddComponent<IReadOnlyMappingManager, AttributesMappingManager>(); 
container.Register(Component.For<ISolrQueryResultParser<Document>>().ImplementedBy<SolrQueryResultParser<Document>>() 
    .ServiceOverrides(ServiceOverride.ForKey("parsers").Eq(new[] { "resultsParser" }))); 
container.AddComponent<ISolrFieldParser, DefaultFieldParser>(); 
container.AddComponent<ISolrDocumentPropertyVisitor, DefaultDocumentVisitor>();

Adding code to profile

We add the code that exercises the components:

var parser = container.Resolve<ISolrQueryResultParser<Document>>(); 

for (int i = 0; i < 1000; i++) { 
    parser.Parse(responseXMLWithArrays); 
} 

Getting the actual profile data

Finally, we get the profile data:

Node<KeyValuePair<MethodInfo, TimeSpan>> rawProfile = container.GetProfile();

This returns a tree of method calls, each with its logged duration. We just want a list of aggregated durations, so first we flatten the tree:

IEnumerable<KeyValuePair<MethodInfo, TimeSpan>> profile = Flatten(rawProfile);

And now we can query and write the profile:

var q = from n in profile 
        group n.Value by n.Key into x 
        let kv = new { method = x.Key, count = x.Count(), total = x.Sum(t => t.TotalMilliseconds)} 
        orderby kv.total descending 
        select kv; 

foreach (var i in q) 
    Console.WriteLine("{0} {1}: {2} executions, {3}ms", i.method.DeclaringType, i.method, i.count, i.total); 

Which prints something like this (prettified):

Method Executions Total own time
AttributesMappingManager.GetFields(Type) 21000 2803.23ms
DefaultDocumentVisitor.Visit(Object, String, XmlNode) 10000 432.19ms
DefaultFieldParser.Parse(XmlNode, Type) 10000 122.77ms
SolrQueryResultParser<Document>.Parse(String) 1000 93.52ms
DefaultFieldParser.CanHandleType(Type) 10000 44.71ms
SolrDocumentResponseParser<Document>.ParseResults(XmlNode) 1000 43.11ms
ResultsResponseParser<Document>.Parse(XmlDocument, SolrQueryResults<Document>) 1000 30.28ms
DefaultFieldParser.CanHandleSolrType(String) 10000 23.78ms

 

Analyzing the profile

Well, it's obvious that AttributesMappingManager.GetFields() is to be blamed here, it's taking a lot of time... which is only logical since it uses a lot of reflection...
But wait a minute, I already thought about that when I wrote that MemoizingMappingManager (which is a memoizer decorator for the AttributesMappingManager)... only I forgot to add it to the container!

Fixing and re-running the profile

After adding the MemoizingMappingManager, the profile comes out like this:

Method Executions Total own time
DefaultDocumentVisitor.Visit(Object, String, XmlNode) 10000 358.64ms
SolrQueryResultParser<Document>.Parse(String) 1000 166.64ms
DefaultFieldParser.Parse(XmlNode, Type) 10000 87.13ms
MemoizingMappingManager.GetFields(Type) 21000 50.5ms
DefaultFieldParser.CanHandleType(Type) 10000 42.03ms
SolrDocumentResponseParser<Document>.ParseResults(XmlNode) 1000 34.93ms
ResultsResponseParser<Document>.Parse(XmlDocument, SolrQueryResults<Document>) 1000 30.83ms
DefaultFieldParser.CanHandleSolrType(String) 10000 22.22ms
AttributesMappingManager.GetFields(Type) 1 19.82ms

 

Conclusion

This cheap profiler has a number of caveats:

  • Since it works by adding a DynamicProxy interceptor to everything, it can only profile interceptable classes and methods managed by Windsor.
  • Times should be taken with a grain of salt. Based on a couple of unscientific tests, it can introduce an error of 10ms (on my machine), rendering a 10ms measured time useless. I'd only use these times for a qualitative comparison. There's a reason why there's a specific .Net profiling API.
  • Multithreading: each thread will get its own interceptor, so each thread gets its own profile.
  • What I just described is not really a test. There is nothing asserted, it can't pass or fail. The "test" here is just a means to run the profile. It should be [Ignore]d.

All in all, I found this to be quite useful. ProfilingContainer is just a thin wrapper around WindsorContainer that adds a ProfilerFacility, which in turn sets up a ProfilingInterceptor. So you could, for example, add the ProfilingInterceptor to your application container with a per-web-request lifestyle and code a HttpModule to profile an entire http request.

Code is here. Sample profile shown in this post is here.

Sunday, May 31, 2009

Duck typing extensions for Windsor

Whenever you have to use some piece of legacy code that's badly designed (i.e. static, no coding to interfaces, god classes), your own code gets tainted with some unwanted dependencies or it gets harder to test because of that unmockable legacy code.

The usual cure for this is to isolate the legacy code with adapters, factories, etc. But what if the legacy code isn't so bad? What if we only need to extract an interface? The resulting adapter would be just trivially forwarding calls to the real object... which is boring code. Can't we do better?

After my last post I've been playing a bit more with David Meyer's Duck Typing Project (aka DeftTech) and thought it would be nice to have the ability to expose a registered Windsor component under one or more duck-typed interfaces. Kind of like forwarded types, but without having the service actually implement those interfaces.

So I came up with a couple of simple extension methods that allow this:

public class Duck {
    public bool HasQuacked { get; private set; }
    public bool HasSwum { get; private set;}

    public void Quack() {
        HasQuacked = true;
    }

    public void Swim() {
        HasSwum = true;
    }
}

public interface IQuack {
    void Quack();
}

public interface ISwimmer {
    void Swim();
}

[Test]
public void WindsorDuckTyping() {
    var container = new WindsorContainer();
    DuckComponentExtensions.Kernel = container.Kernel;
    container.AddFacility<FactorySupportFacility>();
    container.Register(Component.For(typeof(Duck))
        .Duck<IQuack>()
        .Duck<ISwimmer>());
    ISwimmer swimmer = container.Resolve<ISwimmer>();
    swimmer.Swim();
    IQuack quack = container.Resolve<IQuack>();
    quack.Quack();
    Duck duck = container.Resolve<Duck>();
    Assert.IsTrue(duck.HasQuacked);
    Assert.IsTrue(duck.HasSwum);
}

So the Duck can be resolved as IQuack even though it doesn't implement IQuack. Here's the code that enables this:

public static class DuckComponentExtensions {
    public static IKernel Kernel { get; set; }

    public static ComponentRegistration<object> Duck<TDuck>(this ComponentRegistration<object> reg) {
        var targetType = reg.Implementation ?? reg.ServiceType;
        if (!DuckTyping.CanCast<TDuck>(targetType))
            throw new ApplicationException(string.Format("Can't duck type '{0}' to type '{1}'", targetType, typeof(TDuck)));
        Kernel.Register(Component.For<TDuck>()
                            .UsingFactoryMethod(k => DuckTyping.Cast<TDuck>(k.Resolve(reg.Name, reg.ServiceType))));
        return reg;
    }
}

Full source code with tests available here.
Apparently the proxies generated by DeftTech can't be proxied by DynamicProxy... so don't try to define any interceptors for these components! Again, the optimal solution would be to implement proper duck-typing with DynamicProxy...

Monday, May 25, 2009

Duck typing with Castle DynamicProxy

I was trying to come up with some duck typing solution using C# 4.0, based on this, and this, when I realized that DynamicProxy could do this without any new language features:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Castle.Core.Interceptor;
using Castle.DynamicProxy;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace DuckTypingTests {
    public class Duck {
        public void Quack() {
            Console.WriteLine("Quack Quack!");
        }

        public void Swim() {
            Console.WriteLine("Swimming...");
        }
    }

    public interface IQuack {
        void Quack();
    }

    public interface ISwimmer {
        void Swim();
    }

    [TestClass]
    public class DuckTypingTests {
        [TestMethod]
        public void DuckTyping() {
            var duck = new Duck();
            duck.As<IQuack>().Quack();
            duck.As<ISwimmer>().Swim();
        }
    }

    public static class DuckTypingExtensions {
        private static readonly ProxyGenerator generator = new ProxyGenerator();

        public static T As<T>(this object o) {
            return generator.CreateInterfaceProxyWithoutTarget<T>(new DuckTypingInterceptor(o));
        }
    }

    public class DuckTypingInterceptor : IInterceptor {
        private readonly object target;

        public DuckTypingInterceptor(object target) {
            this.target = target;
        }

        public void Intercept(IInvocation invocation) {
            var methods = target.GetType().GetMethods()
                .Where(m => m.Name == invocation.Method.Name)
                .Where(m => m.GetParameters().Length == invocation.Arguments.Length)
                .ToList();
            if (methods.Count > 1)
                throw new ApplicationException(string.Format("Ambiguous method match for '{0}'", invocation.Method.Name));
            if (methods.Count == 0)
                throw new ApplicationException(string.Format("No method '{0}' found", invocation.Method.Name));
            var method = methods[0];
            if (invocation.GenericArguments != null && invocation.GenericArguments.Length > 0)
                method = method.MakeGenericMethod(invocation.GenericArguments);
            invocation.ReturnValue = method.Invoke(target, invocation.Arguments);
        }
    }
}

Again, this is just a spike, it only matches methods, not properties, and even the method matching in the interceptor will break with method overloading. And let's not mention performance.

It would be interesting to somehow merge David Meyer's Duck Typing Project into Castle DynamicProxy, as it is the most complete duck-typing solution for .net that I know...

Tuesday, May 12, 2009

Abusing using to prioritize threads

Welcome to another chapter of "Abusing Using"! IDisposable has been used or abused (depending on who you ask) to create scopes/contexts of all sorts, from database testing to HTML generation to clipboard overriding. Here's another little (ab)use: thread priority setting, for all those background tasks that eat our CPUs:

public static class ThreadSettings {
    private class DisposableThreadPriority: IDisposable {
        private readonly ThreadPriority originalPriority;

        public DisposableThreadPriority(ThreadPriority p) {
            originalPriority = Thread.CurrentThread.Priority;
            Thread.CurrentThread.Priority = p;
        }

        public void Dispose() {
            Thread.CurrentThread.Priority = originalPriority;
        }
    }

    public static IDisposable LowestPriority {
        get {
            return new DisposableThreadPriority(ThreadPriority.Lowest);
        }
    }
}

I like to keep this in an interceptor so I can easily apply it to different components just by adding a couple of lines in my web.config:

public class LowPriorityInterceptor : IInterceptor {
    public void Intercept(IInvocation invocation) {
        using (ThreadSettings.LowestPriority) {
            invocation.Proceed();
        }
    }
}

Friday, May 1, 2009

Windsor - configurable component initialization

This question was raised on the Castle forums a couple of days ago:

I have a third party dependency. It uses a property class for configuration with only a default constructor.

public class Properties { 
      public Properties() {...} 

      public void Add(string name, string value) {...} 
} 

I would love to be able to invoke the .Add to setup this object. Something like this:

<components> 
  <component id="Properties" type="Example.Properties, thirdParty"> 
    <Add> 
      <name>key1</name> 
      <value>value1</value> 
    </Add> 
    <Add> 
      <name>key2</name> 
      <value>value2</value> 
    </Add> 
  </component> 
</components> 

I do realize that I could write an adapter class to interact with the Properties class and then di the adapter. But I'm wondering if I'm missing something or if there is a reason that method invocation is not supported.

Windsor has so many extensibility points that sometimes I have a hard time picking the right one. Windsor lets you change, override or customize almost every aspect of its behaviour thanks to its extensible design. To solve this one, I chose to override the default component activator. The component activator is the internal service responsible for instantiating the component object. To quote Windsor's reference manual:

The ComponentActivator takes a few steps to create the instance

  • Selects the constructor it can satisfy more parameters
  • Creates the instance using the constructor selected
  • Tries to supply dependencies to properties
  • Runs the commission phase lifecycle steps (if any was registered)

Our custom activator will call the default activator, then "deserialize" the method calls from the configuration to the appropriate MethodInfo objects, and finally call those methods on the component instance. We can use the componentActivatorType attribute to select the custom activator.

Here's a demo:

[TestFixture]
public class Tests {
    public class MyComponent {
        public int C { get; private set; }

        public void Add(int i) {
            C += i;
        }

        public void NoParameters() {
            C += 2;
        }
    }

    [Test]
    public void Init() {
        var c = new WindsorContainer(new XmlInterpreter(new StaticContentResource(@"<castle>
<components>
<component id=""mycomponent"" type=""WindsorInitConfig.Tests+MyComponent, WindsorInitConfig"" componentActivatorType=""WindsorInitConfig.InitComponentActivator, WindsorInitConfig"">
<init>
    <Add>
        <i>5</i>
    </Add>
    <Add>
        <i>3</i>
    </Add>
    <NoParameters/>
</init>
</component>
</components>
</castle>")));
        Assert.AreEqual(10, c.Resolve<MyComponent>().C);
    }
}

 

You can checkout the whole code here. Note that this is not really production-quality code: it's not properly tested and it probably won't work on generic methods and overloaded methods with the same parameter names, but it's enough for most cases. Please feel free to enhance it and send me a patch! :-)

Thursday, April 2, 2009

Using Windsor in F#

I've been doing some experiments with F# which involves using Windsor (my default choice for a IoC container) and found that Windsor's fluent interface is... not so fluent when used in F#.

UPDATE 10/21/2010: The F# team has loosened the syntax a lot, F# 2.0 can now consume the Windsor fluent API without any changes.

Fluent interface as-is in F#

Example: given this code in C#

container.Register(Component.For<IMyServiceContract>().ImplementedBy<MyServiceImpl>());

Let's try to translate this to F#. (I'll do it step by step so it's more didactic)

Code: container.Register(Component.For<IMyServiceContract>().ImplementedBy<MyServiceImpl>())
Compiler says: Error: Successive arguments should be separated by spaces or tupled, and arguments involving function or method applications should be parenthesized.
Explanation: Component.For<IMyServiceContract>() is a method application, so it has to be parenthesized:

Code: container.Register((Component.For<IMyServiceContract>()).ImplementedBy<MyServiceImpl>())
Compiler says: Error: Type constraint mismatch. The type ComponentRegistration<IMyServiceContract> is not compatible with type IRegistration array.
The type 'ComponentRegistration<IMyServiceContract>' is not compatible with the type 'IRegistration array'.
Explanation: The reason for these errors is that F# expects an array as the parameter for Register, since it's signature is

IWindsorContainer Register(params IRegistration[] registrations)

and F# doesn't support params arrays, so we have to explicitly construct an array:

Code: container.Register([|(Component.For<IMyServiceContract>()).ImplementedBy<MyServiceImpl>()|])
Compiler says: Error: This expression has type ComponentRegistration<IMyServiceContract> but is here used with type IRegistration.
Explanation: What? But ComponentRegistration<IMyServiceContract> implements the IRegistration interface! Yeah, but Register() takes an array of IRegistration, not an array of ComponentRegistration<IMyServiceContract>, and F# doesn't implement array covariance. You can write this in C#:

IMyServiceContract[] arr = new MyServiceImpl[] { new MyServiceImpl() };

but you can't write this in F#:

let arr: IMyServiceContract[] = [| MyServiceImpl() |]

This is actually a Good Thing since this kind of covariance has some nasty consequences. So we have no option but to cast:

Code: container.Register [| (((Component.For<IMyServiceContract>()).ImplementedBy<MyServiceImpl>()) :> IRegistration) |]
Compiler says: Warning: This expression should have type 'unit', but has type 'IWindsorContainer'.
Explanation: We have to do something about the return value. We're not using it in this example, so we'll just discard it:

Code: let _ = container.Register [| (((Component.For<IMyServiceContract>()).ImplementedBy<MyServiceImpl>()) :> IRegistration) |]

This finally compiles, but it's way too noisy. Not fluent at all!

We could have also written:

let _ = container.Register(Seq.to_array (Seq.cast [(Component.For<IMyServiceContract>()).ImplementedBy<MyServiceImpl>()]))

but it's just as ugly.

Extension method solution

We could hide the casting and array stuff in an extension method:

module WindsorContainerExtensions = 
    type IWindsorContainer with
        member x.RegisterComponents (r: seq<#IRegistration>) = 
            let _ = x.Register (Seq.to_array (Seq.cast r))
            () 

which allows us to write:

container.RegisterComponents [(Component.For<IMyServiceContract>()).ImplementedBy<MyServiceImpl>()]

Much better, but it doesn't quite fit the F# spirit.

Function pipelines solution

A better-yet solution is to use function pipelining to build a DSL, like FsUnit and FsTest do, so we can write:

typeof<IMyServiceContract>
    |> implementedBy (typeof<MyServiceImpl>)
    |> registerIn container

Here are the functions that support this:

let implementedBy impl (service: Type) =
    (Component.For service).ImplementedBy impl       
    
let registerIn (container: IWindsorContainer) registration = 
    container.RegisterComponents [ registration ]

It's easy to follow this pattern and implement similar functions to cover more functionality. For example, this sets the lifestyle for a registration:

let withLifestyle lifestyle (registration: ComponentRegistration<_>) = 
    (registration.LifeStyle).Is lifestyle

Usage:

typeof<IMyServiceContract>
    |> implementedBy (typeof<MyServiceImpl>)
    |> withLifestyle LifestyleType.Transient
    |> registerIn container


Conclusion

Fluent interfaces are cool but quite language-dependent, so if you're designing an API targeting the CLR and thinking of building a fluent interface, make sure you also provide an alternative, simpler, non-fluent API so other languages can build their own flavor of fluent interface (Windsor does provide this, of course)

Wednesday, March 4, 2009

Windsor facility for Quartz.NET

A few months ago I wrote a couple of adapters to integrate Quartz.Net into Windsor. These were loose components that you had to register yourself and the configuration wasn't very friendly. So I decided to wrap them in a facility to make things cleaner and easier.

This is what the facility provides:

Here's what it doesn't support:

  • These entities are NOT Windsor-managed (they are instantiated normally by Quartz instead)
  • Trigger and job group names

Note that it's up to you to register jobs with the appropriate lifestyle. Listeners can only have singleton lifestyle since they're injected in IScheduler which is itself a singleton.

Here are the bits:

Tuesday, February 10, 2009

ARFetch for ASP.NET MVC

I'm currently in the unfortunate position of having to merge part of a MonoRail + ActiveRecord + Windsor (the full Castle stack) project with a huge existing Webforms project. I have to use existing master pages and lots of user controls, and MonoRail's support for these is rather scarce, so I thought of using ASP.NET MVC instead of trying to cram things into webforms. I already had Windsor working on the webforms project, setting up ActiveRecord is a snap, and integrating ASP.NET MVC with Windsor is a breeze thanks to MvcContrib. But I couldn't find anything to integrate ASP.NET MVC with ActiveRecord.

Luckily, MonoRail's IParameterBinder and ASP.NET MVC's IModelBinder aren't that different in spirit. In order to implement ARFetching, I only had to make a couple of minor changes to the ARFetcher and ARFetchAttribute classes.

Here's what a simple CRUD controller would look like using ARFetch:

public class PersonController : Controller {
  //
  // GET: /Person/

  public ActionResult Index() {
      return View(ActiveRecordMediator<Person>.FindAll());
  }

  //
  // GET: /Person/Details/5

  public ActionResult Details([ARFetch("id")] Person person) {
      if (person == null)
          return RedirectToAction("Index");
      return View(person);
  }

  //
  // GET: /Person/Create

  public ActionResult Create() {
      return View();
  }

  //
  // POST: /Person/Create

  [AcceptVerbs(HttpVerbs.Post)]
  public ActionResult Create(FormCollection collection) {
      try {
          var p = new Person();
          UpdateModel(p, collection.ToValueProvider());
          ActiveRecordMediator<Person>.Save(p);
          return RedirectToAction("Index");
      } catch {
          return View();
      }
  }

  //
  // GET: /Person/Edit/5

  public ActionResult Edit([ARFetch("id")] Person person) {
      return View(person);
  }

  //
  // POST: /Person/Edit/5

  [AcceptVerbs(HttpVerbs.Post)]
  public ActionResult Edit([ARFetch("id")] Person person, FormCollection collection) {
      try {
          UpdateModel(person, collection.ToValueProvider());
          ActiveRecordMediator<Person>.Update(person);
          return RedirectToAction("Index");
      } catch {
          return View();
      }
  }
}

Here's the full source code, all merit goes to the Castle team, any bugs are mine:

Sunday, December 7, 2008

Castle Windsor factory method support

After using ninject for a short project (some modifications to a Subtext blog) I came back to Windsor and found myself missing ToMethod(). ToMethod() in ninject gives you factory method support, that is, you pass it a Func and the container will call it whenever it needs to instantiate the component.

Now Windsor has had factory support for years, but it requires the factory to be a class, registered as a component in the container. This is ok as it's the most flexible approach, but sometimes all you need is a factory method, and creating a class and then registering it seems a bit overkill. It would be nicer to write something like:

Container.Register(Component.For<HttpServerUtilityBase>()
   .FactoryMethod(() => new HttpServerUtilityWrapper(HttpContext.Current.Server))
   .LifeStyle.Is(LifestyleType.Transient));

With this little extension method, you can do just that:

    public static class ComponentRegistrationExtensions {
        public static IKernel Kernel { private get; set; }

        public static ComponentRegistration<T> FactoryMethod<T, S>(this ComponentRegistration<T> reg, Func<S> factory) where S: T {
            var factoryName = typeof(GenericFactory<S>).FullName;
            Kernel.Register(Component.For<GenericFactory<S>>().Named(factoryName).Instance(new GenericFactory<S>(factory)));
            reg.Configuration(Attrib.ForName("factoryId").Eq(factoryName), Attrib.ForName("factoryCreate").Eq("Create"));
            return reg;
        }

        private class GenericFactory<T> {
            private readonly Func<T> factoryMethod;

            public GenericFactory(Func<T> factoryMethod) {
                this.factoryMethod = factoryMethod;
            }

            public T Create() {
                return factoryMethod();
            }
        }
    }

 

Of course, this needs the FactorySupportFacility to be installed:

Container.AddFacility("factory.support", new FactorySupportFacility());

And since this isn't really a part of the Kernel, it needs a reference to the container's kernel:

ComponentRegistrationExtensions.Kernel = Container.Kernel;

UPDATE 5/7/2009: I submitted a patch which Ayende applied in revision 5650 so this is now part of the Windsor trunk, only instead of FactoryMethod() it's called UsingFactoryMethod()

UPDATE 7/30/2010: as of Windsor 2.5, UsingFactoryMethod() no longer requires the FactorySupportFacility.

Wednesday, October 8, 2008

Basic Quartz.Net-Windsor integration

A couple of months or so ago, I had to code some periodic maintenance jobs to be run in-process. So I was faced with the same options that Ayende had a year ago (except the out-of-process options). I finally decided on using Quartz.NET, since I needed the dynamic update capabilities (that is, it watches the config file for changes and re-schedules accordingly) which Castle.Components.Scheduler doesn't have yet as far as I know... (BTW Castle.Components.Scheduler is now part of the trunk).

So I set to code the wrappers needed to make it play with Windsor, and the resulting code is here. There's a sample app that shows how to set up job and trigger listeners (both global and job-specific). The actual scheduling configuration is managed by Quartz.NET of course. In the sample I used the external quartz_jobs.xml config with the default RAMJobStore, but you could easily change that to a ADOJobStore or anything, just by setting the props dictionary on the QuartzNetScheduler component, that dictionary is passed as-is to Quartz.NET.

Why did I write "basic" integration on the title? Well, I just needed the basic features of Quartz.NET, so I didn't even try to integrate stuff like clustering, remote servers, etc. I have no idea if those will work with my code. If anyone gives it a try, I'd love to hear about it :-)

UPDATE 4/3/2009: I wrapped the components in a facility for easier usage and configuration.

Saturday, September 6, 2008

Changing Windsor components configuration at runtime

Most of the time you want your services/websites/systems running non-stop. I mean, why would you ever want to be restarting them every 4 minutes? You want to minimize downtime. One cause of app restarting in .NET is having to modify web.config / app.config. To partially address that, I wrote a DynamicConfigurationSettings class some time ago, which basically mimics a web.config but freely modifiable at runtime. Now, let's say you have an app with hundreds of components registered in a Windsor container, all configured in your web.config or windsor.boo file. How could you change a component's properties without restarting your app? Even if you put your container config in another file, if you change it nothing happens until the file is re-parsed and re-processed, which basically means recycling the app.

Example

A sample case could be a SMTP mail sender component, which could look like this:

public class SmtpMailSender : IEmailSender
{
    public SmtpMailSender(int port, string host)
    {
        ...
    }  
    ...
}

and configured like this:

<configuration>
    <components>
        <component id="smtp.sender" 
            service="Namespace.IEmailSender, AssemblyName"
            type="Namespace.SmtpMailSender, AssemblyName">
            <parameters>
                <port>10</port>
                <host>smtp.mycompany.com</host>
            </parameters>
        </component>
    </components>
</configuration>

Now suddenly, the mail server goes down! The ops team, a.k.a. you :-), quickly sets up a second mail server at smtp6.myothercompany.com:25, but you have to point the smtp component to the new server while you investigate what happened to the other. If you touched the config, the site would be recycled, and bad things could happen:

  • If you use InProc sessions (which is the default), all your users lose their sessions.
  • If you use inproc cache (which is the default), you lose all your cache.
  • If any user was in the middle of a payment transaction (using a payment gateway like VeriSign PayPal), you could lose the transaction

Solution

But Windsor is very flexible, so you could tie your components configuration to a dynamic.web.config using this simple SubDependencyResolver:

public class DynamicAppSettingsResolver : ISubDependencyResolver {
   public string Key(ComponentModel model, DependencyModel dependency) {
       return string.Format("{0}.{1}", model.Implementation, dependency.DependencyKey);
   }

   public object Resolve(CreationContext context, ISubDependencyResolver parentResolver, ComponentModel model, DependencyModel dependency) {
       var key = Key(model, dependency);
       return Convert.ChangeType(DynamicConfigurationSettings.AppSettings[key], dependency.TargetType);
   }

   public bool CanResolve(CreationContext context, ISubDependencyResolver parentResolver, ComponentModel model, DependencyModel dependency) {
       var key = Key(model, dependency);
       return dependency.DependencyType == DependencyType.Parameter &&
              !string.IsNullOrEmpty(DynamicConfigurationSettings.AppSettings[key]);
   }
}

Adding this resolver using AddSubResolver, gives you the ability to override components parameters in the appSettings section of your dynamic.web.config:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>    
    <appSettings>
        <add key="Namespace.SmtpMailSender.host" value="smtp6.myothercompany.com"/>
        <add key="Namespace.SmtpMailSender.port" value="25"/>
    </appSettings>
</configuration>

Caveats

This solution has some caveats:

  • The component modifiable with this method (let's call it component A) has to be transient (default is singleton)! Otherwise the subresolver will never get a chance to set the new values...
    Also, as a consequence, other components (let's call them group B) depending on component A have to be transient as well, or they will be stuck with a SmtpMailSender with the old values! And yet other components (group C), depending on any component of group B, have to be transient for the same reason, and so on.
  • This subresolver only works with basic types. Ints and strings are all I have needed so far. Of course, you could swap that Convert.ChangeType() with type converters or the other TypeConverters, or store the settings in a configSection of its own instead of appSettings for more flexibility.
  • It does not support (although it wouldn't be very difficult to do) service overriding, it only does parameter overriding.

Tuesday, July 15, 2008

Castle Facility for SolrSharp

Some months ago I wrote SolrNet, an interface to Solr, mainly because I thought SolrSharp (the standard Solr interface for .net) was too verbose and IoC-unfriendly. I still think that way, but I always wondered what it would take to integrate it to Windsor (or any other IoC container, for that matter).

And the answer is... 241 lines of code (as per "wc -l *.cs"). That's it. That's all it took to write some interfaces and adapters and then wrap them in a Castle facility. That should teach me to try a bit harder next time! :-)

SolrNet was designed with IoC in mind, so integration is just a matter of registering a component:

<component id="solr" service="SolrNet.ISolrOperations`1, SolrNet" type="SolrNet.SolrServer`1, SolrNet">
    <parameters>
        <serverURL>http://localhost:8983/solr</serverURL>
    </parameters>
</component>

Code is here. Note that it's just a proof of concept, I barely tested it!

Monday, July 14, 2008

A few less strings in MonoRail


In the same spirit as my previous post, I wrote a couple of extensions methods to avoid strings when redirecting in Castle MonoRail.
Let's say you have this controller:
public class HomeController : SmartDispatcherController
{
public void Index()
{
}

public void SaveInformation(String name, int age, DateTime dob)
{
// work work work

// Send the user back to the index
RedirectToAction("index");
}
}

Now you can write the redirect like this:

this.RedirectToAction(c => c.Index());

It also works with parameters, i.e. if you have an action like this:

public void Index(int a) {}

you can do:

this.RedirectToAction(c => Index(1));

and it will redirect to /home/index.castle?a=1 (or whatever extension you're using)

It even works with objects and [DataBind] (with some limitations, see below):

public class Properties {
public int SomeValue { get; set; }
}

public class SmartTest2Controller : SmartDispatcherController {
public void DataBinding([DataBind("prefi")] Properties prop) {}
public void Index() {
this.RedirectToAction(c => c.DataBinding(new Properties {SomeValue = 22}));
}
}

Which will redirect to /SmartTest2/DataBinding.castle?prefi.SomeValue=22

There's also support for [ARDataBind] and [ARFetch]:

    public class ARController : ARSmartDispatcherController {
public void Index() {
this.RedirectToAction(c => c.ARFetchAction(new Entity { PK = 5, Name = "Robert Duvall" }));
this.RedirectToAction(c => c.ARAction(new Entity { PK = 4, Name = "John Q" }));
}
public void ARAction([ARDataBind("pre")] Entity e) {}
public void ARFetchAction([ARFetch("pre")] Entity e) { }
}

Which would respectively redirect to /AR/ARFetchAction.castle?pre=5 and /AR/ARAction.castle?pre.PK=4&pre.Name=John+Q
(I was watching John Q while writing this :-) )

ActiveRecord support is implemented in another assembly, to cleanly separate the dependencies. When using the ActiveRecord extensions, you have to initialize it in your Application_Start():

Setup.ForAll(new DefaultExtensionsProvider {ExtUtils = new ARUtils()});
This instructs the extension methods to use the ActiveRecord helpers.

Code is here, let me know your opinion...

Caveats / limitations (for now):
  • Doesn't work with nested object databinding
  • Doesn't work with arrays of objects
  • Works on Castle RC3. Trunk has been refactored a lot regarding controllers since RC3, so this code would have to be adapted (extending IRedirectSupport instead of Controller and such)

UPDATE 5/16/2009: I just found out there already was a similar project on castle contrib.

Thursday, January 3, 2008

Castle Facility for Windows Fax Services

Some months ago, at work I was facing the need to send faxes from the main application server. "No problem", you might say, "just use Windows Fax Services". But the fax server was far, far away, only to be accessed through the internet. So I wrote a wrapper Castle facility around the fax API and published it as a SOAP-WS. Interfaces and implementation are in separate assemblies, so the ws-client doesn't have to depend on fxscomex.dll et al (the Windows Fax DLLs). It is also possible to send faxes via email, by setting up a couple of components outside the facility. These components periodically check an IMAP account for the destination fax number from the subject and the actual fax as an attachment. Usually you would send a TIF or PDF for faxing. Plain text also works, but I guess nobody would use that...

Ok, here's a more formal documentation:

Usage

The facility (Castle.Facilities.WindowsFax.dll) should be installed and configured on the machine that is the direct client of the fax server.

Required assemblies:

  • Castle.Facilities.WindowsFax.dll
  • Castle.Components.Fax.WindowsFaxService.dll
  • Castle.Components.Fax.dll
  • Castle.Core.dll
  • Castle.MicroKernel.dll
  • Interop.FAXCOMEXLib.dll
  • Windows Fax installed

Those are the bare minimum assemblies required, however you probably already have also Castle.Windsor, so I'm going to assume that for the rest of this documentation. If you don't have Windsor for some reason, you'll have to configure it manually using MicroKernel or provide your own configuration.

Configuration

<facility id="fax" type="Castle.Facilities.WindowsFax.WindowsFaxFacility, Castle.Facilities.WindowsFax">
  <serverName>localhost</serverName>
</facility>

<serverName> refers to the machine that has the actual Windows Fax Service running, the one with the actual fax hardware. If not specified, localhost is assumed.

To make a fax operation, ask the Windsor container for Castle.Components.Fax.IFaxService, it has all the operations.

Scenario 1: Local fax server

If your fax server is on the web server's network, just drop the configuration above in your windsor config, setup the fax server name and you're good to go.

Scenario 2: Fax server is on another network

Here you can use the SOAP web services provided (client proxy here) or alternatively use remoting, WCF, etc. Leaving firewalls aside, it looks like this:

 

Dibujo3

 

Required assemblies on "Web App Server":

  • Castle.Components.Fax.dll
  • Castle.Components.Fax.WebServiceClient.dll

On "Fax Web Server", just install the web service provided.

Sending faxes by email

The web service miniapp also comes with the optional components to send faxes via mail. It works by periodically polling an IMAP account for mails with subject with the format "<fax number>, <fax subject>"

  • IMAPClientWrapper is just a wrapper around Lumisoft's excellent IMAP Client.
  • MailFaxSender is the one that does the actual work of checking the mail account and sending any pending faxes found.
    This component takes the following configuration:
    • Username, Password: to access the IMAP account
    • Server, ServerPort: to the IMAP server
    • FolderInbox: IMAP folder where to look for new faxes
    • FolderError: IMAP folder where faxes processed with errors are stored.
    • FolderSent: IMAP folder where sent faxes are stored.
    • FolderNotFax: IMAP folder where mails not related to the fax service (ie doesn't comply with the subject format specified above) are stored.
    These IMAP folders are automatically created when needed.
  • MailSenderScheduler is a basic scheduler that executes the IMAP polling every x minutes. It relies on the startable facility to be...er... started.
    Configuration: SleepingMinutes: pretty much self explanatory.

Troubleshooting

  • Problem: I can't perform any fax operation, I always get some COM Operation Failed exception.
    Solution: Make sure the fax service is running. If it's not that, it's probably a matter of permissions. Open the Fax Console, Tools -> Fax Service Manager, right-click on Fax (Local), Properties, Security tab, allow all operations to the user running the facility (probably NETWORK SERVICE or ASPNET). Also check the permissions on the fax printer: from the Fax Console, Tools -> Fax Printer Configuration, Security tab, etc.
  • Problem: I can't send PDF files.
    Solution: Install Acrobat 4, then modify the path on the registry file acrobat_printto.reg, then apply that reg. UPDATE: also try HKCR\AcroExch.Document.x\shell\Printto\command (where x is the acrobat version)
    Explanation: Windows fax services sends different file types by printing them internally to the fax printer. This registry modification tells Windows to use Acrobat 4 to print the PDF. Why Acrobat 4 and not the latest version? Because Adobe has removed the support in Reader to directly print a PDF. UPDATE: turns out this still works with Acrobat 8.1. Couldn't get it working with Acrobat 9 though.
  • Problem: I can't send DOC (Word) files.
    Solution: DOC files are not supported (if you find something to print docs on the server reliably (ie NOT Microsoft Word) please tell me)

TODO

  • Generalize it to support Hylafax and other fax providers.
  • Support POP3

Project homepage at SourceForge.

SVN repository.

Sunday, June 10, 2007

Exception Translation with Castle Windsor

Warning: the following code has become obsolete since the release of Castle RC3. I'll update as soon as I can. The concepts still apply, though.

Recently I've been writing an app using Castle Windsor. While I was writing the service classes, the following problem came up: I don't want my services' consumers catching Dao exceptions. I'm using ActiveRecord to persist domain objects, but it could have been directly NHibernate, or iBatis. Either way, whoever uses the service classes should be ignorant about persistance details. Suppose the service interface looks like this:

public interface ISomeService {
 void ProvideService();
}
and its implementation lets an internal exception pass, which we could model like this to make things simple:
public class SomeService : ISomeService {
 public void ProvideService() { 
   throw new InternalException();
  }
}

public class InternalException : ApplicationException {}
Now we'd like to translate InternalException into an ExternalException, which is a service-level exception. We could manually catch InternalException in every method of SomeService, but that's annoying.
Let's use Windsor instead. We need three components: the exception translator (which says what external exception corresponds to each internal exception), the interceptor (which actually does the try..catch) and a contributor (which installs the interceptor and translator).
First, let's write a test that should pass when we finish installing all three components:
[TestFixture]
public class ExceptionTranslatorTests {
  [Test]
  [ExpectedException(typeof (ExternalException), "1")]
  public void ExceptionIsTranslated() {
    IWindsorContainer container = new WindsorContainer();
    container.AddComponent("service", typeof (ISomeService), typeof (SomeService));
    ISomeService svc = container.Resolve<ISomeService>();
    svc.ProvideService();
  }
}

public class ExternalException : ApplicationException {
  public ExternalException(string message) : base(message) {}
  public ExternalException() {}
  public ExternalException(string message, Exception innerException) : base(message, innerException) {}
}
If we run this test now, it will fail, since the exception thrown by ProvideService() is still InternalException instead of the expected ExternalException.
Now let's build the translator:
public interface IExceptionTranslator {
 Exception translate(Exception e);
}

public class SomeExceptionTranslator : IExceptionTranslator {
  public Exception translate(Exception e) {
    return new ExternalException("1", e);
  }
}
Simple, no? Just make sure you wrap the original exception, so you don't lose stack information and stuff.
Now for the generic interceptor:
public class ExceptionTranslationInterceptor<T> : IMethodInterceptor where T : IExceptionTranslator {
  private T translator;

  public ExceptionTranslationInterceptor(T translator) {
   this.translator = translator;
  }

  public object Intercept(IMethodInvocation invocation, params object[] args) {
    try {
      return invocation.Proceed(args);
    } catch (Exception e) {
      throw translator.translate(e);
    }
  }
}
Notice that the actual translation logic will be injected by Windsor into the interceptor. Oh, and make sure theIMethodInterceptor you implement is the one in Castle.Core.Interceptor, not the one in AopAlliance.Intercept.
You may wonder why the interceptor takes <T>, you'll see why in a second when we build the contributor:
public class ExceptionTranslatorContributor<T, T2> : IContributeComponentModelConstruction
 where T2 : IExceptionTranslator {
  public void ProcessModel(IKernel kernel, ComponentModel model) {
    if (typeof (T).IsAssignableFrom(model.Implementation)) {
      kernel.AddComponent(typeof (T2).ToString(), typeof (T2));
      kernel.AddComponent(string.Format("ExceptionTranslationInterceptor<{0}>", typeof(T2)), typeof(ExceptionTranslationInterceptor<T2>));
      model.Interceptors.Add(new InterceptorReference(typeof (ExceptionTranslationInterceptor<T2>)));
    }
  }
}

This contributor takes two types: T, which is the service to intercept, and T2, which is the IExceptionTranslator. It installs the translator and the corresponding interceptor as components, then it installs the interceptor as such. By making the interceptor and the contributor generic, we can easily associate different translators for different services, just by setting up the contributor in the container, like this:
[TestFixture]
public class ExceptionTranslatorTests {
  [Test]
  [ExpectedException(typeof (ExternalException), "1")]
  public void ExceptionIsTranslated() {
    IWindsorContainer container = new WindsorContainer();
    container.Kernel.ComponentModelBuilder.AddContributor(new ExceptionTranslatorContributor<SomeService, SomeExceptionTranslator>());
    container.AddComponent("service", typeof (ISomeService), typeof (SomeService));
    ISomeService svc = container.Resolve<ISomeService>();
    svc.ProvideService();
  }
}
And now the test passes!
Full code shown here is available here.