Разрешение общих аргументов конструктора в Castle с наследованием и без интерфейсов

Хотя я и раньше использовал дженерики в Castle Windsor, эта конкретная комбинация в настоящее время поставила меня в тупик.

Я хотел бы разрешить его как аргумент конструктора, который моделируется в этом модульном тесте путем явного вызова метода resolve().

Но я не могу понять, какую комбинацию регистрации и разрешения мне нужно сделать. Я показываю код с неудачным тестом ниже, чтобы прояснить проблему.

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

person PandaWood    schedule 20.01.2014    source источник


Ответы (2)


Во-первых, необходимо зарегистрировать открытый универсальный тип LogConfig<>, как это сделал @Marwijn.

Затем вы можете зарегистрировать все реализации BaseSettings<T>, выбрав базовый тип/условие и сервис для компонента используя BasedOn(typeof(BaseSettings<>)) и WithService.Base().

Следующий метод испытаний доказывает это:

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

Есть еще один ответ на аналогичный вопрос о регистрации типов на основе базового класса< /а>.

person Ilya Palkin    schedule 20.01.2014
comment
Хорошее улучшение. Спасибо, я не знал, что это основано на работах с открытыми дженериками. - person Marwijn; 21.01.2014
comment
Фантастика да, это то, что мне нужно - person PandaWood; 22.01.2014

Вы можете попробовать это:

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

Удачи, Марвейн.

person Marwijn    schedule 20.01.2014