【问题标题】:In C#, how do I keep certain method calls out of the codebase entirely?在 C# 中,如何将某些方法调用完全排除在代码库之外?
【发布时间】:2011-02-23 17:55:21
【问题描述】:

我正在尝试摆脱所有DateTime.Now 方法调用,并用我自己的GetNow() 方法替换它们,该方法有时可能会返回一个固定日期以进行测试。

如何强制以后没有人添加DateTime.Now 调用?我可以使用 NDependStyleCop 在我的持续集成服务器上进行检查吗?

【问题讨论】:

  • 它是DateTime.Now,就像“它是一个属性”,而不是DateTime.Now(),就像“它是一个函数”一样
  • 这是一个有效的问题,但我想知道这个例子的智慧。用有时返回不同时间的代码替换旧的DateTime.Now?您最好在测试期间调整系统时钟,不是吗?
  • 为什么你允许我希望只在内部测试期间使用的方法在集成服务器上使用?您应该使用 DateTime.Now 而不是静态方法,如果您忘记实时环境中的某些内容,可能会返回不正确的值。

标签: c# methods


【解决方案1】:

使用 NDepend 很容易write this rule:

// <Name>Forbid DateTime.Now, use xxx.GetNow() instead</Name>
WARN IF Count > 0 IN 
SELECT METHODS WHERE 
IsDirectlyUsing "OPTIONAL:System.DateTime.get_Now()"

注意:

  • 前缀 WARN IF Count > 0 IN 将 CQL 查询转换为规则
  • 通过字符串System.DateTime.get_Now()引用属性的方式
  • 前缀 OPTIONAL 表示“如果找不到属性 get_Now,则不发出编译错误”。这是有道理的,因为如果您的代码不再使用 get_Now(),NDepend 分析将不再引用它。

另外,要生成原始查询...

SELECT METHODS WHERE 
IsDirectlyUsing "OPTIONAL:System.DateTime.get_Now()"

...只需右键单击 DateTime.get_Now() 并选择 选择直接使用我的方法...

【讨论】:

  • 嘿帕特里克,是否有一个查询会考虑到特定方法的所有潜在重载?例如,如果我(为了论证)想在任何时候使用 NDepend 来禁止或警告我看到代码“new Foo()”,以及变体“new Foo(1)”、“new Foo(' bar')"等,我可以通过CDL查询吗?
  • 只有将CQL查询中的所有重载一一列举才可能。在 NDepend 的下一个主要版本中,可以一目了然地匹配所有重载。
【解决方案2】:

首先,DateTime.Now 是一个属性
这意味着您不需要在调用后加上括号。

其次,如果测试目的是指 NUnit 之类的框架,您可能需要查看 Microsoft Moles,它允许您在测试时用您自己的自定义实现替换任何静态方法调用。哎呀,这很酷:

[Test]
[ExpectedException (typeof (Y2KBugException))]
public void TestY2KBug ()
{
    MDateTime.NowGet = () => new DateTime (2001, 1, 1);
    Bomb.DetonateIfY2K ();
}


public static class Bomb {
    public static void DetonateIfY2K ()
    {
        if (DateTime.Now == new DateTime (2001, 1, 1))
            throw new Y2KBugException (); // take cover!
    }
}

【讨论】:

【解决方案3】:

没有真正的方法来强制执行这样的事情。

您最接近的是 making a custom FxCop 规则或 custom Visual Studio Code Analysis rule 在调用 DateTime.Now 时出现错误/警告。

【讨论】:

  • 贾斯汀,是的,这是可能的,并且很容易使用 NDepend 强制执行此类要求,请参阅下面的答案。
【解决方案4】:

您可以在测试中使用Moles 在需要时提供您自己的 DateTime.Now,而无需修改任何调用它的现有代码。

另一种选择可能是在编译后修改程序集以调用其他内容。 (或许可以用 Mono.Cecil 重写 IL,在 VS 的 post-build 中添加命令运行。)

您也许可以获取 Mono 源代码并自己构建一个自定义 mscorlib,并删除该函数。

【讨论】:

    【解决方案5】:

    一种方法可能是向您选择的源代码控制存储库添加一个预提交挂钩,以查找DateTime.Now,如果您发现有问题的字符串,则中止签入。这不是万无一失的,它可能会让您的同事感到烦恼,但它应该有助于将其排除在代码库之外。

    【讨论】:

      【解决方案6】:

      我认为这是不可能的。您实际上想要做的是覆盖 DateTime 的结构功能。

      我能想到的唯一方法就是使用一个自定义类,该类将包装 DateTime 的常见功能并按需提供不同的功能...

      【讨论】:

        猜你喜欢
        • 2019-09-24
        • 1970-01-01
        • 2017-10-02
        • 1970-01-01
        • 2012-06-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多