我正在编写一个(非常小的)框架来检查方法的前置条件和后置条件。入口点是(它们很容易是方法;这并不重要):

public static class Ensures {
    public static Validation That {
        get { ... }
    }
}

public static class Requires {
    public static Validation That {
        get { ... }
    }
}

显然,当方法没有错误时,检查后置条件可能会很昂贵,并且实际上没有必要。所以我想要一个像这样工作的方法:

public static class Ensures {
    [ConditionalCallingCode("DEBUG")]
    public static Validation ThatDuringDebug {
        get { ... }
    }
}

在哪里 ConditionalCallingCodeAttribute 意味着此方法仅应在使用定义的 DEBUG 符号编译调用代码时运行。这可能吗?

我希望客户端代码如下所示:

public class Foo {
    public void Bar() {
        ... // do some work
        Ensures.That // do these checks always
            .IsNotNull(result)
            .IsInRange(result, 0, 100);

        Ensures.WhileDebuggingThat // only do these checks in debug mode
            .IsPositive(ExpensiveCalculation(result));

        return result;
    }
}

当然,我可以干脆不提供WhileDebuggingThat。那么客户端代码将如下所示:

public class Foo {
    public void Bar() {
        ... // do some work
        Ensures.That // do these checks always
            .IsNotNull(result)
            .IsInRange(result, 0, 100);

        #ifdef DEBUG
        Ensures.That // only do these checks in debug mode
            .IsPositive(ExpensiveCalculation(result));
        #endif

        return result;
    }
}

如果没有其他办法的话,这是后备计划,但它确实严重破坏了 DRY。

据我了解,标记 WhileDebuggingThat[Conditional("DEBUG")] 将发出(或不发出)此方法,具体取决于在库编译期间是否定义了 DEBUG, 不是 引用该库的程序集。所以我 可以 执行此操作,然后编写文档,告诉库用户将其代码的调试版本与库的调试版本链接起来,并将发布版本与发布版本链接起来。我认为这不是最好的解决方案。

最后,我可以告诉库用户在他们的项目中定义此类:

using ValidationLibrary;
public static class EnsuresWhileDebugging {
    [Conditional("DEBUG")]
    public static Validation That() {
        return Ensures.That;
    }
}

据我所知,这应该也有效,但仍然需要打破 DRY 原则,哪怕只是稍微打破一下。

有帮助吗?

解决方案

这是在这里发现的任何解决方案将是比实际检查慢。此外,由于它不会被打造成为类的编译ConditionalAttribute,参数仍然会被计算。如果后置条件可能是非常复杂的,如

Ensures.That.IsPositive(ExpensiveCalculation(result));

您可能会考虑使用icelava的建议,以反映调用程序集找到,如果它是建立在调试或释放 - 但你的必须的使用某种形式的委托延迟计算 - 确保在需要的时候它只是做。 e.g:

Ensures.WhileDebugging.That. IsPositive(() => ExpensiveCalculation(result));

在IsPositive函数应该运行拉姆达并检查其结果,仅反射,以找出是否应当计算之后。

其他提示

这是任何正常 ConditionalAttribute 你从一个属性,而不是方法的工作没有做,一边?你可能需要改变的东西被称为这样,你有方法,而不是属性的方式 - 而它返回的值可能会导致问题的事实。

这将有很大的帮助,如果你想展示你的框架是如何使用 - 目前我们还没有得到很多与工作

考虑将提供多种二进制的另一件事,建立资料库的 - 这样,来电者可以只提供一个不同的版本,它实际上并不做任何检查。再次,虽然,这很难说,只有您所提供的代码。

自从我要洗澡并离开家以来,我还没有尝试过这个。

  1. 调用 Assembly.GetCallingAssembly() 获取调用当前执行方法的方法(类)所在的程序集。
  2. 对该 Assembly 对象运行检查以查看它是发布版本还是调试版本.

这听起来像极了你在做什么用Debug.Assert()已经被覆盖。

对于这个问题,这个代码将永远只能在调试模式下运行(但你必须要忍受追块缓慢):

try
{
     Debug.Assert(false);
}
catch (Exception e)
{
     // will only and always run in debug mode

}

看来,我要的只是不可用。我可能会沉降从Validation提供的隐式转换到bool,以便验证检查可以包裹在Debug.Assert()

在调试Assert方法可以使用程序编译即使,例如,如果值是从一个项目用户SETING截取的布尔来设置/改变:

Debug.Assert(!Properties.Settings.Default.UseAutoDebug);

我不知道,但我认为你可以使用ConditionalAttribute此:是否要发出呼叫或不发射将取决于类型的用户打造,不是你的图书馆。您可以使用反射或ILDASM检查此:编译你的样品和反射器(ILDASM)看呼叫是发出与否样本项目

我出现这种情况:项目A调用B的1函数。B 包括这个功能:assembly.getCallingAssembly()。全​​名如果在模式调试中构建B然后运行,则此功能返回项目A的名称,如果在模式下构建比项目B的返回名称。我不知道发生这种情况的原因。请支持我谢谢

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top