On Castle Windsor and open generic component arity

In the previous post I said there’s one more new feature in Windsor 3.2 related to open generic components.

Take the following class for example:

public class Foo<T, T2> : IFoo<T>
{
}

Notice it has arity of 2 (two generic parameters, T and T2) and the interface it implements has arity of 1.
If we have a generic component for this class what should be supplied for T2 when we want to use it as IFoo<Bar>?

By default, if we just register the component and then try to use it we’ll be greeted with an exception like the following:

Requested type GenericsAndWindsor.IFoo`1[GenericsAndWindsor.Bar] has 1 generic parameter(s), whereas component implementation type GenericsAndWindsor.Foo`2[T,T2] requires 2.
This means that Windsor does not have enough information to properly create that component for you.
You can instruct Windsor which types it should use to close this generic component by supplying an implementation of IGenericImplementationMatchingStrategy.
Please consut the documentation for examples of how to do that.

Specifying implementation generic arguments: IGenericImplementationMatchingStrategy

The IGenericImplementationMatchingStrategy interface allows you to plug in your own logic telling Windsor how to close the implementation type for a given requested service. The following trivial implementation simply uses string for the other argument, therefore allowing the component to be successfully constructed.

public class UseStringGenericStrategy : IGenericImplementationMatchingStrategy
{
	public Type[] GetGenericArguments(ComponentModel model, CreationContext context)
	{
		return new[]
		{
			context.RequestedType.GetGenericArguments().Single(),
			typeof (string)
		};
	}
}

The contract is quite simple, given a ComponentModel and CreationContext (which will tell you what the requested closed type is) you return the right types to use for generic arguments when closing the implementation type of the model.

You hook it up in exactly the same way as IGenericServiceStrategy (and yes, there’s an overload that allows you to specify both).

container.Register(Component.For(typeof (IFoo<>))
	.ImplementedBy(typeof (Foo<,>), new UseStringGenericStrategy())
	.LifestyleTransient());

Now the service will resolve successfully.
Generic component resolved

On Castle Windsor and open generic components

While Windsor supported open generics components since pretty much forever, there’s been some improvements in version 3.2 that I haven’t blogged about yet, but which can be pretty useful in some advanced scenarios. I’ll cover them in this and future blogpost.

Just so we’re clear – what are open generic components?

So what are open generic components? Components based on a generic type where we don’t specify the generic arguments. Like the following:

// register
container.Register(Component.For(typeof (IFoo<>))
	.ImplementedBy(typeof (Foo<>))
	.LifestyleTransient());

// will provide IFoo<Bar>, IFoo<Baz>, IFoo<any_valid_type>

In this case we say that the component provides IFoo<> closed over Bar, Baz etc

Being picky about what we’re closing over: IGenericServiceStrategy

Sometimes we want to restrict the types we want our components to support. C# language allows us to use generic constraints to specify that, and Windsor will obviously respect that, but sometimes we need to go beyond what language provides.

One realistic example might be restricting to specific types from a given assembly, like in this StackOverflow question.

Windsor 3.2 has a new hook point for just that – IGenericServiceStrategy, which allows you to plug custom logic to specify whether you want a component to support a given closed version of it’s open generic service.

Here’s a sample implementation limiting to types from a single assembly:

public class OnlyFromAssemblyStrategy : IGenericServiceStrategy
{
	private readonly Assembly assembly;

	public OnlyFromAssemblyStrategy(Assembly assembly)
	{
		this.assembly = assembly;
	}

	public bool Supports(Type service, ComponentModel component)
	{
		return service.GetGenericArguments().Single().Assembly == assembly;
	}
}

To hook the strategy:

container.Register(Component.For(typeof (IFoo<>))
	.ImplementedBy(typeof (Foo<>), new OnlyFromAssemblyStrategy(someAsembly))
	.LifestyleTransient());

Now when you need IFoo<SomeTypeFromWrongAssembly> either another component will need to supply it, or the dependency will not be satisfied (which, if the dependency is not optional, will result in exception).
Component Not Found exception

Castle Windsor 3.0 is released

Castle Windsor

After successful beta and RC releases final version of Castle Windsor (as well as Castle Core, and a whole set of facilities) has now been released. There are no major changes between final version and RC. The difference is some minor bug fixes, improved exception messages and some small improvements all over the place.

 

The packages are available now, on Nuget (with symbols), and via standard .zip download.

 

Last but not least – thank you to everyone who downloaded beta and release candidate and provided feedback. You guys rock.

Windsor 3 beta 1 – dozen of Nuget packages and SymbolSource.org support

As promised, I released Nuget packages for beta 1 of Windsor 3. This is my first major rollout of Nuget packages, so please report any issues working with them.

Nuget and beta packages

Nuget is quickly evolving and getting more useful with each release. However one feature it’s missing right now is support for pre-release packages (this is coming in the next version).

davidebbo

This is not really a big deal, however it means there are a few things you should be aware of.

Recommended version

Since the new package is a pre-release, while I would really like for everyone to start using it immediately and report all issues they find, I quite understand that many people will rather prefer to stick to the last official version for the time being. To accommodate that the new packages are not made recommended versions, so your Nuget explorer will still point to the last stable (2.5.3) version if you search for Windsor, Castle.Core or any other pre-existing package.

nuget_explorer 

If you go to command line and install one of the packages without specifying version number, it will install the latest, that is beta 1 version.

nuget_commandline

SymbolSource.org and debugging into Windsor

Folks at SymbolSource.org added recently support for Nuget (and OpenWrap as well) and the new Castle packages take advantage of that. What it gives you, is you can now easily debug into Windsor’s code, just like .NET framework reference source (there’s a simple guide at SymbolSource on how to do it).

After you’re all set you can step into any of Castle methods in your debugger and watch the magic happen. Very cool thing, even if I say so myself.

windsor-source-debugging

 

List of packages

Here’s the full list of v3 beta 1 packages (notice those are not all Castle packages, just those that were published as v3 beta 1 rollout of Windsor):

 

I hope this will make it easier for everyone to test drive Windsor. And if you find any issues, have any suggestions or ideas, do not hesitate to bring them up, either on our google group, or issue tracker.