2011-11-16 108 views
1

我有以下靜態屬性定義:類型初始拋出異常,同時訪問靜態屬性

namespace Foo 
{ 
    public class Bar 
    { 
     private static byte[] aes256Key = null; 
     internal static byte[] Aes256Key 
     { 
      get 
      { 
       if (aes256Key != null) 
       { 
        return aes256Key; 
       } 

       aes256Key = new byte[32]; 

       // Fill in key... 

       return aes256Key; 
      } 
     } 
    } 
} 

在另一大類內部的命名空間內,我訪問此屬性:

namespace Foo.Cryptography 
{ 
    public class SymmetricCryptography 
    { 
     internal static void EncryptFile(
      string sourceFile, 
      string destinationFile) 
     { 
      // <snip> 
      AesManaged aes = new AesManaged(); 
      aes.BlockSize = 128; 
      aes.KeySize = 256; 
      aes.Key = Bar.Aes256Key; // Accessing the key here 
      // <snip> 
     } 
    } 
} 

Foo.Cryptography使用由可執行控制檯應用程序。當我從構建環境手動運行此控制檯應用程序時,我看不到任何問題。然而,當可執行文件生成過程的範圍內(有可能不同環境中的服務器上)跑,我看到下面的運行時異常:

The type initializer for 'Foo.Bar' threw an exception. 

在VS2008的可執行項目具有對Foo參考該項目定義了Foo命名空間。

我在這裏做了什麼根本錯誤嗎?什麼可能導致這個?

+0

類型初始值設定項非常好,我喜歡和下一個人一樣使用它們,但是我已經遠離將它們用於除絕對最簡單的任何事情之外的任何東西,因爲它們在炸燬時不會提供非常好的反饋。如果這個異常不在類型初始化器中,你可能會收到一個實際有用的消息。 –

+1

我會說要採取任何類型初始化代碼,並將其推遲到類型初始化後,以便您可以得到一個更好的錯誤消息,但它看起來不像類型初始化程序中的任何事情看起來很多你提供的代碼。 –

+1

在發佈的代碼中沒有類型初始值設定項。沒有需要初始化的字段,並且代碼中未顯示靜態類型初始值設定項。因此,這裏沒有人可以回答爲什麼代碼失敗,因爲你沒有發佈該代碼。請發佈其餘的字段聲明,如果你有它,你的靜態類型初始化器。 –

回答

0

Foo.Aes256Key甚至不會編譯,因爲Foo是你的命名空間...

+0

對不起,更正了代碼。它編譯時,我只是在提交問題時更改了名稱空間/類的名稱(有點不正確,看起來)。 – LeopardSkinPillBoxHat

0

是Foo.Cryptography和Foo.Bar在同一個DLL?聽起來像一個依賴性問題,就像它無法找到包含Foo.Bar的硬盤驅動器上的DLL。

編輯:好吧上面顯然不是問題...

也許你正在使用的初始化類要求的依賴,這不是生產機器上......我看不到任何東西你的代碼,但也許是你遺漏的部分。我假設你已經在生產機器上加載了完整的.net框架。你是否在你遺漏的代碼中使用了任何對象,直接或間接地調用其他內部或第三方dll的代碼?

另一個編輯:其實我不認爲你遺漏部分的代碼會導致這個錯誤,因爲它不應該在類初始化時自動運行。你確定沒有其他的代碼可以離開嗎?我在這裏沒有看到任何可能會導致這種異常的東西。

它看起來像「private static byte [] aes256Key = null;」是唯一能夠引起這種異常的線路,但我認爲這條線路不會那麼做。

+0

如果它們位於不同的dll中,請嘗試手動檢查包含Foo.Bar的dll是否與包含Foo.Cryptography的dll位於同一目錄中(如果它與應用程序目錄不同,請嘗試確保它在那裏可用太)。如果這樣可以修復你的錯誤,那麼你知道你的發行版中只有一個問題。 –

+0

謝謝,但它們在同一個DLL中。 – LeopardSkinPillBoxHat

+0

哎呀,剛纔意識到我並沒有完全想直接......這顯然是找到了Foo.Bar,因爲它可以到達其初始化類型。我會更新我的答案,希望更有用... –

1

如果沒有看到完整的代碼,在'靜態世界'上工作真的很難。儘管如此,爲了找到原因,以下幾個領域可以(個人)工作。

aes256Key = new byte[32]; 
// Fill in key... 
return aes256Key; 
  1. 這是合理的檢查可能的例外在「關鍵填寫」邏輯

  2. 定義靜態構造函數這個酒吧和初始化所有的靜態字段。

  3. 確保您在訪問任何static/instance field/member/method之前致電以下RuntimeHelpers.RunClassConstructor(typeof(Bar).TypeHandle)

    static void Main(string[] args)

    {

    RuntimeHelpers.RunClassConstructor(typeof(Bar).TypeHandle); 
    byte[] bt = Bar.Aes256Key; 
    

    }

RuntimeHelpers.RunClassConstructor不要求運行時調用靜態構造函數,無論在CLI中指定的原因。這確保了確定性的單元初始化順序。這是必要的,因爲類型初始化器相信Lazy初始化。

+0

除了特殊代碼外,您不應該依賴或使用'RuntimeHelpers.RunClassConstructor'。 – user7116

相關問題