Question

Though I've used generics in Castle Windsor before, this particular combination has currently got me stumped.

I'd like to resolve it as a constructor argument, which is simulated in this unit test by explicitly calling resolve().

But I cannot figure out what combination of registration and resolving I need to do. I show the code with a failing test, below, to make the problem clear.

    public abstract class BaseSettings<T> where T : class
    {
        protected void Save(T obj)
        { }
    }

    public class AddinSettings : BaseSettings<AddinSettings>
    { }

    public class OtherSettings : BaseSettings<OtherSettings>
    { }

    public class LogConfig<T> where T : class
    {
        private readonly BaseSettings<T> _client;

        public LogConfig(BaseSettings<T> client)
        {
            _client = client;
        }

        public BaseSettings<T> Client
        {
            get { return _client; }
        }
    }

    [Test]
    public void resolve_generics()
    {
        var container = new WindsorContainer();
        container.Register(Component.For<OtherSettings >());
        var otherSettings = container.Resolve<LogConfig<OtherSettings>>();
        Assert.That(otherSettings, Is.Not.Null);
    }
Was it helpful?

Solution

First, it is needed to register an open generic type LogConfig<> as @Marwijn did.

Then, you can register all BaseSettings<T> implementations by means of selecting base type/condition and service for the component using BasedOn(typeof(BaseSettings<>)) and WithService.Base().

The following test method proves it:

[TestMethod]
public void resolve_generics()
{
    // arrange
    var container = new WindsorContainer();
    container.Register(
        Component.For(typeof(LogConfig<>)),
        Classes.FromThisAssembly().BasedOn(typeof(BaseSettings<>)).WithService.Base());

    //act
    var otherSettings = container.Resolve<LogConfig<OtherSettings>>();
    var addinSettings = container.Resolve<LogConfig<AddinSettings>>();

    // assert
    otherSettings.Should().NotBeNull();
    otherSettings.Client.Should().BeOfType<OtherSettings>();

    addinSettings.Should().NotBeNull();
    addinSettings.Client.Should().BeOfType<AddinSettings>();
}

There is another answer on the similar question about registering types based on base class.

OTHER TIPS

You can try this:

container.Register(
    Component.For(typeof(LogConfig<>)),
    Component.For<BaseSettings<OtherSettings>>().ImplementedBy<OtherSettings>());

Goodluck, Marwijn.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top