2008-12-27 20 views
1

我正在寫一個(非常小的)框架來檢查方法的前置和後置條件。入口點是(他們可以很容易地方法,這並不重要):.Net中是否有可能僅從客戶端程序集的調試版本調用某些代碼?

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原則,如果只是輕微。

+0

這不是什麼斷言? – 2008-12-27 13:29:17

+0

斷言適用於檢查後置條件(僅適用於調試版本;我希望允許在發佈版本中保留後續檢查),而不驗證前置條件。 – 2008-12-27 14:05:24

回答

1

是在這裏找到任何解決辦法會比實際的要慢檢查。另外,由於它不會像ConditionalAttribute那樣編譯到編譯器中,參數仍將被計算。如果後置條件可能會非常複雜,比如

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

您可以考慮使用icelava的建議,以反映調用程序集找到,如果它是建立在調試或釋放 - 但你必須使用某種形式的委託人推遲計算 - 以確保只在需要時才執行。例如:

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

IsPositive函數應該運行lambda並檢查其結果,只有在反映後才能確定它是否應該計算。

3

這是否正常ConditionalAttribute不會爲你做的任何事情,除了在一個屬性而不是一個方法?您可能需要改變事情的調用方式,以便獲取方法而不是屬性 - 而且它返回值的事實可能會導致問題。

如果你能展示你的框架是如何使用的話,這將有很大的幫助 - 目前我們還沒有很多工作要做。

要考慮的另一件事是提供庫的各種二進制版本 - 以便調用者可以提供不實際執行任何檢查的不同版本。雖然如此,只用您提供的代碼很難說清楚。

0

這聽起來像你正在做的大部分已經覆蓋使用Debug.Assert()

對於這個問題,這個代碼將永遠只能在調試模式下運行(但你必須要忍受追塊緩慢):

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

} 
+0

Debug.Assert()僅適用於後置條件。如果我想要使用相同的API來驗證前置和後置條件,或者輕鬆地在僅調試和經常檢查的後置條件之間切換,則不適用。 – 2008-12-27 17:38:58

0

看來,我想要的只是不可用。我可能會承諾提供從Validationbool的隱式轉換,以便可以將驗證檢查包裝在Debug.Assert()中。

0

調試斷言方法可以使用布爾程序編譯即使,例如,如果該值是從一個項目的用戶SETING採取設置/改變:

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

我不知道,但我認爲你可以使用ConditionalAttribute這個:是否發出呼叫或不發出將取決於用戶的構建類型,而不是你的庫。您可以使用Reflector或ILDasm來檢查:編譯您的示例並在Reflector(ILDasm)中查看示例項目中是否發出調用。

0

我有這種情況發生: 項目B的通話1個功能 分別包括這樣的功能:。 Assembly.GetCallingAssembly()全名 如果在模式調試版本B,則運行,項目A的這個函數返回的名字,如果在模式發佈版本比返回項目B的名稱。 我不知道發生這種情況的原因。 請支持我 謝謝

相關問題