必须证明基类属性在所有派生类中不变?

发布于 2024-09-14 16:29:54 字数 1438 浏览 7 评论 0原文

我有一个基类,在其中尝试使用空对象模式来提供默认记录器实现,然后可以在稍后阶段通过 IoC setter 注入来更改该实现。

public interface ILog
{
    void Log(string message);
}

public class NoOpLogger: ILog 
{
    public void Log(string message)
    { }
}

public abstract class ClassWithLogger
{
    private ILog _logger = new NoOpLogger();

    protected ClassWithLogger()
    {
        Contract.Assert(Logger != null);
    }

    public ILog Logger
    {
        get { return _logger; }
        set
        {
            Contract.Requires(value != null);
            _logger = value;
            Contract.Assert(Logger != null);
        }
    }

    [ContractInvariantMethod]
    private void ObjectInvariant()
    {
        Contract.Invariant(Logger != null);
    }
}

public sealed class DerivedClass : ClassWithLogger
{
    private readonly string _test;
    public DerivedClass(string test)
    {
        Contract.Requires<ArgumentException>(!String.IsNullOrWhiteSpace(test));
        _test = test;

        // I get warning at end of ctor: "invariant unproven: Logger != null"
    }

    public void SomeMethod()
    {
        Logger.Log("blah");
    }
}

正如我在代码中指出的,我的问题是,我在派生类的构造函数末尾收到一条警告,指出基类的“Logger!= null”对象不变性尚未得到证明,即使很明显没有任何变化Logger 属性值,我还在 setter 周围签订了合同,以确保它永远不会为空。

有什么方法可以避免在所有派生类中重新证明这一事实,或者这只是静态分析器的限制?

更新:问题已在最新版本的 CodeContracts 中得到解决。另外,我不再需要抽象基类构造函数中的断言(“Contract.Assert(Logger != null);”行)

I have a base class in which I'm trying to use the Null Object pattern to provide a default logger implementation which can then be changed by IoC setter injection at a later stage.

public interface ILog
{
    void Log(string message);
}

public class NoOpLogger: ILog 
{
    public void Log(string message)
    { }
}

public abstract class ClassWithLogger
{
    private ILog _logger = new NoOpLogger();

    protected ClassWithLogger()
    {
        Contract.Assert(Logger != null);
    }

    public ILog Logger
    {
        get { return _logger; }
        set
        {
            Contract.Requires(value != null);
            _logger = value;
            Contract.Assert(Logger != null);
        }
    }

    [ContractInvariantMethod]
    private void ObjectInvariant()
    {
        Contract.Invariant(Logger != null);
    }
}

public sealed class DerivedClass : ClassWithLogger
{
    private readonly string _test;
    public DerivedClass(string test)
    {
        Contract.Requires<ArgumentException>(!String.IsNullOrWhiteSpace(test));
        _test = test;

        // I get warning at end of ctor: "invariant unproven: Logger != null"
    }

    public void SomeMethod()
    {
        Logger.Log("blah");
    }
}

As I indicate in the code, my issue is that I get a warning at the end of the derived class' constructor saying that the "Logger != null" object invariant from the base class has not been proven even though it's obvious nothing has changed the Logger property value and I also have contracts around the setter to ensure it can never be null anyway.

Is there any way to avoid having to reprove this fact in all derived classes, or is this just a limitation of the static analyser?

UPDATE: Problem has been fixed in latest version of CodeContracts. Also, I don't need the assert in the abstract base class constructor anymore (the line "Contract.Assert(Logger != null);")

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

洛阳烟雨空心柳 2024-09-21 16:29:54

我刚刚测试了您发布的代码,它工作得很好。您是否使用最新版本的代码合约 (1.4.30707.2)?

I just tested your code as posted and it worked fine. Are you using the most recent version of Code Contracts (1.4.30707.2)?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文