Замок Виндзор, выбор реализации сервиса в зависимости от некоторых параметров контекста

С Castle Windsor 3.2 мне нужно разрешить реализацию сервиса на лету в зависимости от контекстных параметров. Вот основной пример того, что я хочу сделать:

У меня есть сервис IFoo

public interface IFoo
{
   object GetSomething();
}

Реализовано 2 разными классами Foo1 и Foo2

public class FooBase
{
   public int Number {get; private set;}

   public FooBase(int number)
   {
      Number = number;
   }
}

public class Foo1 : IFoo
{
   public Foo1(int number):base(number)
   public object GetSomething()
   {
      return "Foo1";
   }
}

public class Foo2 : IFoo
{
   public Foo2(int number):base(number)
   public object GetSomething()
   {
      return "Foo2";
   }
}

Я хочу вызвать метод разрешения замка Виндзора с номером в качестве параметра, и в зависимости от номера, я хочу иметь объект Foo1 или Foo2:

var foo1 = container.Resolve<IFoo>(new {number= 1});
// foo1 is Foo1
var foo2 = container.Resolve<IFoo>(new {number= 2});
// foo2 is Foo2

Я испробовал несколько потенциальных решений, но я действительно запутался из-за отсутствия документации и примеров Castle Windsor, добавив, что большинство примеров устарели и используют устаревший API.

Итак, я видел некоторый пример, использующий следующие концепции, но ни один из них не показался мне более подходящим:

  1. HandlerSelector
  2. Типизированный завод
  3. UsingFactoryMethod

2 ответа

Используйте следующий регистрационный код:

container = new WindsorContainer();
        container.AddFacility<TypedFactoryFacility>();
        container.Register(
            Component.For<FooSelector>,
            Component.For<Foo1>(),
            Component.For<Foo2>(),
            Component.For<IFooFactory>().AsFactory(c => c.SelectedWith<FooSelector>())
        );

Создать фабрику Foo:

public interface IFooFactory
{
    IFoo CreateFoo(int number);
}

и селектор:

public class FooSelector : DefaultTypedFactoryComponentSelector
{
    protected override Type GetComponentType(System.Reflection.MethodInfo method, object[] arguments)
    {
        var argument = (int) arguments[0];
        if (argument == 1) return typeof (Foo1);
        if (argument == 2) return typeof(Foo2);
        throw new ApplicationException();
    }
}

Теперь разрешите IFooFactory и вызовите метод create со значением, которое вы хотите.

С наилучшими пожеланиями, Marwijn.

Вот код, который работал для меня:

container = new WindsorContainer();
        container.AddFacility<TypedFactoryFacility>();
        container.Register(
            Component.For<IFoo>().ImplementedBy<Foo1>().Named("Foo1"),
            Component.For<IFoo>().ImplementedBy<Foo2>().Named("Foo2"),
            Component.For<IFooFactory>().AsFactory(c => c.SelectedWith<FooSelector>())
        );

Создать фабрику Foo:

public interface IFooFactory
{
    IFoo CreateFoo(int number);
}

и селектор:

public class FooSelector : DefaultTypedFactoryComponentSelector
{
    protected override string GetComponentName(System.Reflection.MethodInfo method, object[] arguments)
    {
        var argument = (int) arguments[0];
        return string.Format("Foo{0}", argument);
    }
}
Другие вопросы по тегам