0

重複の可能性:
.NET NUnitテスト-Assembly.GetEntryAssembly()がnull

ロギングライブラリを書いています。ライブラリは、デフォルトで、アプリケーションに名前が付けられた共通のアプリケーションデータフォルダー内のディレクトリに書き込みます。たとえば、アプリケーションの名前が「MyApplication.exe」の場合、データを「C:\ ProgramData\MyApplication」に保存します。

私はこのコードを使用してパスを作成しています:

   private static string loggingDataPath = 
      Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) +
      Path.DirectorySeparatorChar + 
      Path.GetFileNameWithoutExtension(Assembly.GetEntryAssembly().CodeBase) +
      Path.DirectorySeparatorChar;

これは期待どおりに機能しますが、1つの問題があります。ライブラリの単体テストができません!

単体テストを実行しようとすると、すべてSystem.NullReferenceExceptionで失敗します。「Assembly.GetEntryAssembly()。CodeBase」呼び出しを文字列に置き換えると、単体テストが再び正しく機能します。

なぜこれが起こるのかは理解できたと思いますが、問題を回避する方法がわかりません。誰かが私を義の道に導いてくれることを願っています。

TIA!

更新(5-24-12):「loggingDataPath」の内容を単体テストしようとはしていません。「Assembly.GetEntryAssembly()。CodeBase」呼び出しが存在するだけで、上記の例外を除いてすべての単体テストが失敗します。「loggingDataPath」は静的であることに注意してください(これは静的ライブラリであるため、静的である必要があります)。

4

2 に答える 2

4

It's not only unit testing that will cause problems.

Given that GetEntryAssembly() can return null when a managed assembly has been loaded from an unmanaged application and also that CodeBase can contain a URL for assemblies downloaded from the Internet, and is not set for assemblies loaded from the GAC, I would avoid attempting this approach for a general-purpose logging library.

If that's not enough to convince you, other problems are (a) non-privileged users won't have write access to CommonApplicationData, and (b) multiple instances of your application attempting to write to the same log file will be a problem.

Instead, I would define the location of the log file in configuration.

Where would you suggest I put it to avoid this problem?

As I said, I would define it in configuration (e.g. an appSetting in app.config). This is the most flexible. If you want to put it under CommonApplicationData, you can use an environment variable that you expand using the Environment.ExpandEnvironmentVariables method when reading from the configuration file. For example:

<appSettings>
    <add key="logFile" value="%ALLUSERSPROFILE%\MyApp\MyLogFile.log" />
    ...
</appSettings>

You still have to solve the problem of giving access to non-privileged users, and avoiding contention when accessing from multiple instances. You say your underlying logging library supports concurrent access, but be aware that this will have a potential performance cost, depending on how verbose your logging is.

于 2012-05-24T13:50:41.083 に答える
0

以前の回答の賢明なアドバイスを無視し、私の質問だけに対処する、これが私が問題を修正した方法です:

   public static string LoggingDataPath { 
      get { 
         return loggingDataPath.Length > 0 ? loggingDataPath : 
         Environment.GetFolderPath(Environment.SpecialFolder.CommonDocuments) + 
         Path.DirectorySeparatorChar + 
         Path.GetFileNameWithoutExtension(Assembly.GetEntryAssembly().CodeBase) + 
         Path.DirectorySeparatorChar; 
      } 

      set { loggingDataPath = value; } 
   } 

このソリューションは、静的クラスへの最初のアクセスで「loggingDataPath」を初期化することを回避し、したがって「Assembly.GetEntryAssembly()。CodeBase」の呼び出しを回避します。

于 2012-05-28T19:25:58.657 に答える