Замок Виндзор: Как указать параметр конструктора из кода? - PullRequest
11 голосов
/ 18 сентября 2008

Скажите, у меня есть следующий класс

MyComponent : IMyComponent {
  public MyComponent(int start_at) {...}
}

Я могу зарегистрировать его экземпляр с помощью Castle Windsor через xml следующим образом

<component id="sample"  service="NS.IMyComponent, WindsorSample" type="NS.MyComponent, WindsorSample">  
  <parameters>  
    <start_at>1</start_at >  
  </parameters>  
</component>  

Как бы я поступил так же, но в коде? (Обратите внимание, параметр конструктора)

Ответы [ 6 ]

16 голосов
/ 18 сентября 2008

Редактировать: Использовал приведенный ниже код с Fluent Interface:)

namespace WindsorSample
{
    using Castle.MicroKernel.Registration;
    using Castle.Windsor;
    using NUnit.Framework;
    using NUnit.Framework.SyntaxHelpers;

    public class MyComponent : IMyComponent
    {
        public MyComponent(int start_at)
        {
            this.Value = start_at;
        }

        public int Value { get; private set; }
    }

    public interface IMyComponent
    {
        int Value { get; }
    }

    [TestFixture]
    public class ConcreteImplFixture
    {
        [Test]
        void ResolvingConcreteImplShouldInitialiseValue()
        {
            IWindsorContainer container = new WindsorContainer();

            container.Register(
                Component.For<IMyComponent>()
                .ImplementedBy<MyComponent>()
                .Parameters(Parameter.ForKey("start_at").Eq("1")));

            Assert.That(container.Resolve<IMyComponent>().Value, Is.EqualTo(1));
        }

    }
}
2 голосов
/ 14 октября 2014

Попробуйте это

int start_at = 1; 
container.Register(Component.For().DependsOn(dependency: Dependency.OnValue(start_at)));
1 голос
/ 07 ноября 2008

Рассматривали ли вы использовать Binsor для настройки вашего контейнера? Вместо многословного и неуклюжего XML вы можете настроить Windsor с помощью DSL на основе Boo. Вот как будет выглядеть ваш конфиг:

component IMyComponent, MyComponent:
   start_at = 1

Преимущество заключается в том, что у вас есть гибкий конфигурационный файл, но вы избежите проблем с XML. Также вам не нужно перекомпилировать, чтобы изменить конфигурацию, как если бы вы сконфигурировали контейнер в коде.

Существует также множество вспомогательных методов, которые позволяют конфигурировать с нулевым трением:

  for type in Assembly.Load("MyApp").GetTypes():
    continue unless type.NameSpace == "MyApp.Services"
    continue if type.IsInterface or type.IsAbstract or type.GetInterfaces().Length == 0
    component type.GetInterfaces()[0], type

С ним можно начать здесь .

0 голосов
/ 17 апреля 2019

Вы можете использовать класс конфигурации для чтения app.config. Затем зарегистрируйте это и заставьте windsor использовать его для своей зависимости. В идеале моя MyConfiguration будет использовать интерфейс.

public class MyConfiguration
{
    public long CacheSize { get; }

    public MyConfiguration()
    {
        CacheSize = ConfigurationManager.AppSettings["cachesize"].ToLong();
    }
}



container.Register(Component.For<MyConfiguration>().ImplementedBy<MyConfiguration>());

container.Register(Component.For<MostRecentlyUsedSet<long>>()
.ImplementedBy<MostRecentlyUsedSet<long>>().
DependsOn(Dependency.OnValue("size", container.Resolve<MyConfiguration>().CacheSize))
.LifestyleSingleton());
0 голосов
/ 18 сентября 2008

Вы можете использовать метод AddComponentWithProperties интерфейса IWindsorContainer для регистрации службы с расширенными свойствами.

Ниже приведен «рабочий» пример выполнения этого с помощью модульного теста NUnit.

namespace WindsorSample
{
    public class MyComponent : IMyComponent
    {
        public MyComponent(int start_at)
        {
            this.Value = start_at;
        }

        public int Value { get; private set; }
    }

    public interface IMyComponent
    {
        int Value { get; }
    }

    [TestFixture]
    public class ConcreteImplFixture
    {
        [Test]
        void ResolvingConcreteImplShouldInitialiseValue()
        {
            IWindsorContainer container = new WindsorContainer();
            IDictionary parameters = new Hashtable {{"start_at", 1}};

            container.AddComponentWithProperties("concrete", typeof(IMyComponent), typeof(MyComponent), parameters);

            IMyComponent resolvedComp = container.Resolve<IMyComponent>();

            Assert.That(resolvedComp.Value, Is.EqualTo(1));
        }

    }
}
0 голосов
/ 18 сентября 2008

Вам нужно передать IDictionary при запросе контейнера для экземпляра.

Вы бы использовали эту перегрузку Resolve IWindsorContainer:

T Resolve<T>(IDictionary arguments)

или не универсальный:

object Resolve(Type service, IDictionary arguments)

Так, например: (при условии, что контейнер является IWindsorContainer)

IDictionary<string, object> values = new Dictionary<string, object>();
values["start_at"] = 1;
container.Resolve<IMyComponent>(values);

Обратите внимание, что значения ключей в словаре чувствительны к регистру.

...