构造函数重构中的虚方法调用

时间:2014-04-03 15:27:38

标签: c# oop refactoring virtual-method

我有一个Client类,它接受构造函数中带有IConfiguration接口的对象。

配置应在创建Client对象时验证。

public interface IConfiguration
{
    int ReconnectDelay { get; }
}

public class Client
{
    public Client(IConfiguration configuration)
    {
        if (configuration.ReconnectDelay < 60000)
        {
            throw new ConfigurationErrorsException();
        }
    }
}

出于测试目的,我需要一个ReconnectDelay属性设置为低于有效值的客户端。

这是我目前的解决方案:

public class Client
{
    public Client(IConfiguration configuration)
    {
        ValidateConfiguration(configuration);
    }

    protected virtual void ValidateConfiguration(IConfiguration configuration)
    {
        if (configuration.ReconnectDelay < 60000)
        {
            throw new ConfigurationErrorsException();
        }
    }
}

public class TestClient : Client
{
    public TestClient(IConfiguration configuration)
        : base(configuration)
    {
    }

    protected override void ValidateConfiguration(IConfiguration configuration)
    {
    }
}

它可以工作,但是会导致在构造函数中调用虚方法,这很糟糕(我知道现在它不会造成任何伤害,但我想解决这个问题。)

那么,对此有什么优雅的解决方案吗?

1 个答案:

答案 0 :(得分:2)

您可以使用2个实现创建Validator接口,然后委托给验证器。从技术上讲,这仍然是一个虚拟调用,但它是另一个对象,因此您不必担心Client的子类会覆盖调用或访问部分构建的客户端。

public interface IValidator
{
    bool Validate (IConfiguration configuration);
}

然后您的正常用例使用ReconnectionValidator。

public class ReconnectionValidator : IValidator
{

     bool Validate (IConfiguration configuration)
     {
       return configuration.ReconnectDelay >= 60000;
     }
}

您的测试验证程序始终可以返回true

public class NullValidator : IValidator
{

     bool Validate (IConfiguration configuration)
     {
       return true;
     }
}

然后,您的客户端代码将在其构造函数中同时使用IValidatorIConfiguration,并测试验证程序是否验证配置。

public Client(IConfiguration configuration, IValidator validator)
{
   if(!validator.Validate(configuration))
   {
        throw new ConfigurationErrorsException();
    }
}

这种技术的好处是你可以稍后更改验证器,或者有一个新的实现,将多个验证器链接在一起以支持&#34;或&#34;和&#34; anding&#34;验证者在一起。