如何在城堡windsor中使用多个键注册多个接口实现?

时间:2011-10-19 22:45:34

标签: c#-4.0 castle-windsor

我有一个类似的验证界面:

public interface IValidation<T> {
  bool IsValid(T item, ref AggregateException fail);
}

我有一个需要多个验证接口的文件导入器

public FileImporter {
  IEnumerable<IValidation<Patient>> Validators { get; set; }

  public FileImporter(IWindsorContainer container) {
    // the ResolveAll method does not do this
    Validators = container.ResolveAll<IValidation<Patient>>("fileValidation");
  }
}

我还有另一个类有更多验证器,但使用的是FileImporter中使用的一些类。

public PatientService {
  IEnumerable<IValidation<Patient>> Validators { get; set; }

  public PatientService(IWindsorContainer container) {
    // the ResolveAll method does not do this
    Validators = container.ResolveAll<IValidation<Patient>>("userInputValidation");
  }
}

例如,我有两个验证器LastNameValidatorDateOfBirthValidatorLastNameValidator is used in both the FileImporter and the PatientService . DateOfBirthValidator is only used in the PatientService`类。这两个类的实现都在问题之下。

我的问题是如何连接这两个类,以便按上述方式使用它们。我应该采用什么方法来解决它们?

public class LastNameValidator : IValidation<Patient> {
  public bool IsValid(Patient p, ref AggregateException fail) {
    var isValid = !string.IsNullOrWhitespace(p.LastName))
    if (!isValid)
        // update fail
    return isValid;
  }
}

public class DateOfBirthValidator : IValidation<Patient> {
  public bool IsValid(Patient p, ref AggregateException fail) {

    if (!p.DateOfBirth.HasValue) {
        // update fail, can't be empty
        return false;
    }
    if (p.DateOfBirth.Value > DateTime.Now) {
        // update fail, can't be in future
        return false;
    }
    return true;
  }
}

1 个答案:

答案 0 :(得分:1)

我会考虑Typed Factory Facility。您可以使用名称“lastnamevalidator”和“dobvalidator”注册验证器。然后创建一个工厂界面来抓取那些特定的验证器。您只需要接口 - 工具将执行:

public interface IValidatorFactory
{
    IValidator GetLastNameValidator();
    IValidator GetDobValidator();
}

现在将IValidatorFactory传递给您的组件。这也消除了传递Windsor容器的需要(这不是一个好主意,因为它将您的代码紧密地耦合到Windsor并使单元测试更加困难)。

现在只需调用工厂方法来访问每个组件所需的特定验证器。

<强>更新

仍然不清楚你的系统的哪个部分将决定使用哪个IValidator,但也许这会起作用。使用基于IValidator的标记接口。

public interface IFileValidator : IValidator
{
}

public interface IUserInputValidator : IValidator
{
}

现在让您的验证器根据它们的使用位置实现标记接口 - 并记住您可以实现多个接口,因此验证器可以在多种情况下使用。例如:

public class FileValidator : IFileValidator
{
    public bool IsValid()
    {
        return false;
    }
}

public class DobValidator : IUserInputValidator, IFileValidator
{
    public bool IsValid()
    {
        return false;
    }
}

public class LastNameValidator : IUserInputValidator
{
    public bool IsValid()
    {
        return true;
    }
}

更改工厂界面以仅返回特定类型的验证器:

public interface IValidatorFactory
{
    IFileValidator[] GetFileValidators();
    IUserInputValidator[] GetUserInputValidators();
}

现在将验证者accorindg注册到他们的“类型”。如果验证器有多种用途,请务必为Windsor添加.Forward<>定义:

var container = new WindsorContainer();
container.AddFacility<TypedFactoryFacility>();
container.Register(
    Component.For<IValidatorFactory>().AsFactory(),

    Component.For<IFileValidator>().ImplementedBy<FileValidator>(),
    Component.For<IUserInputValidator>().ImplementedBy<LastNameValidator>(),
    Component.For<IFileValidator>().Forward<IUserInputValidator>().ImplementedBy<DobValidator>()
    );