Castle Windsor Fluent API: явное определение зависимости - PullRequest
2 голосов
/ 16 марта 2009

Учитывая приведенную ниже конфигурацию

        Container.Register(Component.For<A>().Named("foo"));
        Container.Register(Component.For<B>().Named("foobar"));

        Container.Register(
            AllTypes.Pick()
            .FromAssemblyNamed("MyAssembly")
            .If(t => t.Name.EndsWith("ABC"))
            .Configure(c => c.LifeStyle.Is(LifestyleType.Transient))
            .WithService.Select(i => typeof(I))
        );

        Container.Register(
            AllTypes.Pick()
            .FromAssemblyNamed("MyAssembly")
            .If(t => t.Name.EndsWith("123"))
            .Configure(c => c.LifeStyle.Is(LifestyleType.Transient))
            .WithService.Select(i => typeof(I))
        );

Если я знаю, что интерфейс «I» предоставляет свойство «P» и что классы A и B могут быть назначены для P; как явно указать, что первая коллекция типов из вызова AllTypes должна иметь свойство P, установленное на тип с идентификатором "foo", а вторая коллекция должна иметь то же свойство, установленное на тип с идентификатором "foobar «

Используя XML-конфигурацию, это можно сделать, явно задав параметры в нотации $ {id}. Я предполагаю, что это похоже на свободный API.

Спасибо.

Ответы [ 3 ]

2 голосов
/ 17 марта 2009

Вы на правильном пути - вам нужно настроить параметры каждого компонента, указав для параметра «P» значение «$ {foo}» или «$ {foobar}» в зависимости от вашего сценария. Вот рабочий факт xunit (прокрутите вниз до самого фактического регистрационного кода), который демонстрирует ваш сценарий.

namespace Question651392
{
  public class First123 : I
  {
    public AbstractLetter P { get; set; }
  }

  public class Second123 : I
  {
    public AbstractLetter P { get; set; }
  }

  public class FirstABC : I
  {
    public AbstractLetter P { get; set; }
  }

  public class SecondABC : I
  {
    public AbstractLetter P { get; set; }
  }

  public interface I
  {
    AbstractLetter P { get; set; }
  }

  public abstract class AbstractLetter
  {
  }

  public class B : AbstractLetter
  {
  }

  public class A : AbstractLetter
  {
  }

  public class RegistrationFacts
  {
    [Fact]
    public void EnsureParametersCanBeSetWhenRegisteringComponentsInBulk()
    {
      WindsorContainer Container = new WindsorContainer();

      Container.Register(Component.For<A>().Named("foo"));
      Container.Register(Component.For<B>().Named("foobar"));

      Container.Register(
          AllTypes.Pick()
          .FromAssembly(GetType().Assembly)
          .If(t => t.Name.EndsWith("ABC"))
          .Configure(c => c.LifeStyle.Is(LifestyleType.Transient))
          .Configure(c=>c.Parameters(Parameter.ForKey("P").Eq("${foo}")))
          .WithService.Select(new[] { typeof(I) })          
      );

      Container.Register(
          AllTypes.Pick()
          .FromAssembly(GetType().Assembly)
          .If(t => t.Name.EndsWith("123"))
          .Configure(c => c.LifeStyle.Is(LifestyleType.Transient))
          .Configure(c => c.Parameters(Parameter.ForKey("P").Eq("${foobar}")))
          .WithService.Select(new[] { typeof(I)})
      );

      var all = Container.ResolveAll<I>();

      var firstABC = all.Single(i => i is FirstABC);
      Assert.IsType(typeof(A), firstABC.P);

      var first123 = all.Single(i => i is First123);
      Assert.IsType(typeof (B), first123.P);

      Assert.Equal(4, all.Count());
    }
  }
}

Надеюсь, это поможет!

1 голос
/ 23 апреля 2011

На самом деле, чтобы добавить к полному ответу @ Bittercoder, рекомендуемый способ сделать это:

.DependsOn(Property.ForKey("P").Is("fooBar"))
1 голос
/ 17 марта 2009

Одна вещь, которую стоит упомянуть при тестировании этого.

Второй настраиваемый вызов отображается для отмены первого вызова.

      .Configure(c => c.LifeStyle.Is(LifestyleType.Transient))
      .Configure(c => c.Parameters(Parameter.ForKey("P").Eq("${foobar}")))

Если добавить к тесту

        var all2 = Container.ResolveAll<I>();
        Assert.IsTrue(all.Count(i => all2.Contains(i)) == 0);

это не удастся, но вы ожидаете, что оно тоже пройдет, так как все объявлено временным. Это означает, что временный образ жизни был утрачен, и вместо него использовался образ жизни по умолчанию для синглтона.

Изменение вызова конфигурации на приведенные ниже приводит к прохождению теста.

        .Configure(c => .LifeStyle.Is(LifestyleType.Transient).Parameters(Parameter.ForKey("P").Eq("${foobar}")))

Спасибо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...