Замок Виндзор, выбор реализации сервиса в зависимости от некоторых параметров контекста
С 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.
Итак, я видел некоторый пример, использующий следующие концепции, но ни один из них не показался мне более подходящим:
- HandlerSelector
- Типизированный завод
- 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);
}
}