我正在编写一个日志库。默认情况下,我希望库写入为应用程序命名的公共应用程序数据文件夹中的目录。例如,如果应用程序名为“MyApplication.exe”,我希望数据保存在“C:\ ProgramData \ MyApplication”中。
我正在使用此代码构建路径:
private static string loggingDataPath =
Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) +
Path.DirectorySeparatorChar +
Path.GetFileNameWithoutExtension(Assembly.GetEntryAssembly().CodeBase) +
Path.DirectorySeparatorChar;
这完全符合预期,有一个问题。我无法对图书馆进行单元测试!
当我尝试运行单元测试时,它们都会因System.NullReferenceException而失败。如果我用字符串替换“Assembly.GetEntryAssembly()。CodeBase”调用,则单元测试再次正常运行。
我想我明白为什么会这样,但我不知道如何解决这个问题。我希望有人能够让我走上正义的道路。
TIA!
更新(5-24-12):我不是要对“loggingDataPath”的内容进行单元测试。仅存在“Assembly.GetEntryAssembly()。CodeBase”调用会导致所有单元测试失败并出现上述异常。请注意,“loggingDataPath”是静态的(因为它必须是静态库)。
答案 0 :(得分:4)
不仅单元测试会导致问题。
鉴于GetEntryAssembly() can return null when a managed assembly has been loaded from an unmanaged application以及CodeBase can contain a URL for assemblies downloaded from the Internet, and is not set for assemblies loaded from the GAC,我会避免尝试将此方法用于通用日志记录库。
如果这还不足以说服你,其他问题是(a)非特权用户将无法对CommonApplicationData进行写访问,并且(b)您的应用程序尝试写入同一日志文件的多个实例将是问题
相反,我会在配置中定义日志文件的位置。
你建议我把它放在哪里以避免这个问题?
正如我所说,我会在配置中定义它(例如app.config中的appSetting)。这是最灵活的。如果要将其置于CommonApplicationData下,则可以使用在从配置文件中读取时使用Environment.ExpandEnvironmentVariables
方法展开的环境变量。例如:
<appSettings>
<add key="logFile" value="%ALLUSERSPROFILE%\MyApp\MyLogFile.log" />
...
</appSettings>
您仍然必须解决访问非特权用户的问题,并避免从多个实例访问时出现争用。您说您的底层日志记录库支持并发访问,但请注意,这将具有潜在的性能成本,具体取决于您的日志记录的详细程度。
答案 1 :(得分: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'。