在构造函数重构中进行虚方法调用

3

我有一个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)
    {
    }
}

它能够工作,但在构造函数中调用虚方法,这是不好的(我知道现在它不会有任何问题,但我仍想解决这个问题)。

所以,有没有优雅的解决方案呢?


你能把 TestClient 类声明为 sealed 吗? - Dmitry
@Dmitry 这会怎么帮助呢?真诚的问题。 - Sriram Sakthivel
@Dmitry,我可以将“TestClient”设为密封的,但问题在于“Client”类。 - bniwredyc
1个回答

2

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

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

然后您的正常使用情况将使用重新连接验证器。
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();
    }
}

这种技术的优点是您可以稍后更改验证器或新实现,将多个验证器链接在一起以支持"或"和"与"验证器。


谢谢,我喜欢你的解决方案。 - bniwredyc
@bniwredyc 很好。我刚刚修复了ReconnectionValidator代码中的一个拼写错误,否则由于我的布尔逻辑相反,它将失败。 - dkatzel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接