如何将模型与其封闭的通用验证器匹配。服务定位器是唯一的答案吗?

时间:2018-03-26 12:10:18

标签: c# design-patterns ioc-container

我有一个Car类型的基类:

public abstract class Car
{
{

大约50种派生类型的汽车,例如:

public class CarA : Car
{
}

public class CarB : Car
{
}
// etc ...

为了使事情更棘手,基类有几个属性也是抽象类型。这些抽象类型具有不同数量的派生类型:

public abstract class Car
{
    public abstract Engine Engine { get; set; }
    public abstract ICollection<Seat> Seats { get; set; }
}

public class CarA : Car
{
    public Engine Engine { get; set; }
    public ICollection<Seat> Seats { get; set; }

    public CarA()
    {
        // Setting defaults.
        Engine = new EngineA();
        Seats = new List<Seat> { new SeatA(), new SeatA(), new SeatB(), new SeatC() };
    }
} 
// etc ...

将这些对象传递给api并在运行时进行反序列化。我的控制器接受基本类型的汽车,我想要做的是验证汽车及其所有属性。在过去,我会为每辆车添加一个IsValid()方法,并在类上调用一个IsValid()方法。这很干净。

public class CarsController : ApiController
{
    [HttpPost]
    public IHttpActionResult AddCar(Car car)
    {
        car.IsValid();
        // Save car to store
    }
}

现在解决问题。

调用IsValid()不允许我进行依赖注入,我希望能够从验证逻辑中分离出模型。

这引入了许多验证类:

public class CarValidator : IValidator<Car>
{
    public bool IsValid(Car car) { // validation logic here }
}

public class CarAValidator : IValidator<CarA>
{
    // The probelm with validating the seats is the same problem as with validating the car.
    // In this case there is only a small number of seat validators so I have injected them all in.
    private readonly ICollection<IValidator<Seat>> seatValidators;

    public CarAValidator(IValidator<Car> baseValidator, ICollection<IValidator<Seat>> seatValidators)
    {
        Include(baseValidator);
        this.seatValidators = seatValidators;
    }

    public bool IsValid(CarA car) { // validation logic here }
}

我希望能够以干净的方式获得与派生类型匹配的验证器。我在网上看到的一些建议包括:

  1. 将IOC容器注入控制器并使用该服务 定位器模式,以找到正确的验证器。
  2. 创建一个使用其中的服务定位器模式的工厂,并将其注入您的控制器。
  3. 注入所有验证器的集合并搜索它们以获得正确的类型。这是我已经使用的appraoch但我担心每次请求必须创建50个验证器,而实际上只需要一个。请记住,每个验证器都可以有许多其他集合用于验证。
  4. 我是否可以使用干净的模式来获取正确类型的正确验证器,还是应该使用服务定位器(反)模式?

0 个答案:

没有答案