地址验证器工厂 - 需要一个参数来选择实现
场景:你需要在提交销售订单时选择地址验证的实施,验证器由订单发货的国家/地区确定。工厂需要检查作为参数传递的一些值以选择正确的实现。
首先,为工厂编写一个接口:
public interface IAddressValidatorFactory
{
IAddressValidator GetAddressValidator(Address address);
void Release(IAddressValidator created);
}
界面表明 IAddressValidator
的实现将由作为 GetAddressValidator
的参数传递的 Address
确定。
当我们向 Windsor 注册同一接口的多个实现时,我们通常将它们命名为。因此工厂需要返回实现的名称。在这种情况下,假设我们在容器中注册了几个 IAddressValidator
的实现:
container.Register(
Component.For<IAddressValidator,UnitedStatesAddressValidator>()
.Named("AddressValidatorFor_USA"),
Component.For<IAddressValidator, FinlandAddressValidator>()
.Named("AddressValidatorFor_FIN"),
Component.For<IAddressValidator, MalawiAddressValidator>()
.Named("AddressValidatorFor_MWI"),
Component.For<IAddressValidator, CommonCountryAddressValidator>()
.Named("FallbackCountryAddressValidator")
.IsDefault()
);
我们工厂的工作将采取一个 Address
并返回 Windsor 将解决的实施名称。这需要一个组件选择器。
public class AddressValidatorSelector : DefaultTypedFactoryComponentSelector
{
public AddressValidatorSelector()
: base(fallbackToResolveByTypeIfNameNotFound: true) { }
protected override string GetComponentName(MethodInfo method, object[] arguments)
{
return "AddressValidatorFor_" + ((Address)arguments[0]).CountryCode;
}
}
该类告诉 Windsor 查找根据订单的国家/地区代码命名的 IAddressValidator
的实现。芬兰的“AddressValidatorFor_Fin”。
如果没有针对该特定国家/地区的验证器,我们可以回退到默认验证器。我们也可以通过使用不同的名称多次注册相同的实现来为多个国家/地区使用相同的验证器。
我们为组件选择器编写了代码,但是我们没有为工厂本身编写代码。温莎提供工厂,我们告诉它使用我们的 AddressValidatorSelector
。
// Add the factory facility once.
container.AddFacility<TypedFactoryFacility>();
container.Register(
Component.For<IAddressValidatorFactory>()
.AsFactory(new AddressValidatorSelector()));
当一个类依赖 IAddressValidatorFactory
时,Windsor 将使用我们提供的组件选择器注入自己的实现。