地址验证器工厂 - 需要一个参数来选择实现

场景:你需要在提交销售订单时选择地址验证的实施,验证器由订单发货的国家/地区确定。工厂需要检查作为参数传递的一些值以选择正确的实现。

首先,为工厂编写一个接口:

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 将使用我们提供的组件选择器注入自己的实现。