是否有方法获取当前代码所在程序集的路径?我不需要调用程序集的路径,只需要包含代码的路径。
基本上,我的单元测试需要读取一些相对于dll的xml测试文件。无论测试dll是否从TestDriven运行,我都希望该路径始终能够正确解析。NET, MbUnit GUI或者别的什么。
编辑:人们似乎误解了我的问题。
我的测试库位于say
C: \ \项目myapplication \ daotests \ bin \ \ daotests.dll调试
我想得到这条路径:
C: \ \ myapplication \ daotests \ bin \项目调试\
到目前为止,当我从MbUnit Gui运行时,这三个建议都失败了:
环境。CurrentDirectory
给出c:\Program Files\MbUnit
System.Reflection.Assembly.GetAssembly .Location (typeof (DaoTests))
给出C:\Documents和
乔治\ \本地设置
设置\ Temp \…\ DaoTests.dll
.Location System.Reflection.Assembly.GetExecutingAssembly ()
给出与前面相同的结果。
我一直在用汇编。用CodeBase代替Location:
Assembly a;
a = Assembly.GetAssembly(typeof(DaoTests));
string s = a.CodeBase.ToUpper(); // file:///c:/path/name.dll
Assert.AreEqual(true, s.StartsWith("FILE://"), "CodeBase is " + s);
s = s.Substring(7, s.LastIndexOf('/') - 7); // 7 = "file://"
while (s.StartsWith("/")) {
s = s.Substring(1, s.Length - 1);
}
s = s.Replace("/", "\\");
它一直在工作,但我不再确定它是100%正确的。http://blogs.msdn.com/suzcook/archive/2003/06/26/assembly-codebase-vs-assembly-location.aspx的网页上写着:
"The CodeBase is a URL to the place where the file was found, while the Location is the path where it was actually loaded. For example, if the assembly was downloaded from the internet, its CodeBase may start with "http://", but its Location may start with "C:\". If the file was shadow-copied, the Location would be the path to the copy of the file in the shadow copy dir.
It’s also good to know that the CodeBase is not guaranteed to be set for assemblies in the GAC. Location will always be set for assemblies loaded from disk, however."
您可能希望使用CodeBase而不是Location。
注:组装。CodeBase在. net Core/中已弃用。NET 5+: https://learn.microsoft.com/en-us/dotnet/api/system.reflection.assembly.codebase?view=net-5.0
最初的回答:
我定义了以下属性,因为我们经常在单元测试中使用它。
public static string AssemblyDirectory
{
get
{
string codeBase = Assembly.GetExecutingAssembly().CodeBase;
UriBuilder uri = new UriBuilder(codeBase);
string path = Uri.UnescapeDataString(uri.Path);
return Path.GetDirectoryName(path);
}
}
大会。Location属性有时会在使用NUnit时给你一些有趣的结果(其中程序集从临时文件夹运行),所以我更喜欢使用CodeBase,它以URI格式给你路径,然后是UriBuild。unescapedatasstring在开始时删除File://, GetDirectoryName将其更改为正常的windows格式。
这是我想到的。在web项目之间,单元测试(nunit和resharper测试运行器);我发现这对我很有用。
我一直在寻找代码来检测构建在什么配置中,调试/发布/定制名。唉,#if DEBUG. #如果有人能改进的话!
请随意编辑和改进。
获取应用程序文件夹。有用的web根,单元测试,以获得测试文件的文件夹。
public static string AppPath
{
get
{
DirectoryInfo appPath = new DirectoryInfo(AppDomain.CurrentDomain.BaseDirectory);
while (appPath.FullName.Contains(@"\bin\", StringComparison.CurrentCultureIgnoreCase)
|| appPath.FullName.EndsWith(@"\bin", StringComparison.CurrentCultureIgnoreCase))
{
appPath = appPath.Parent;
}
return appPath.FullName;
}
}
获取bin文件夹:用于使用反射执行程序集。如果文件复制到那里由于构建属性。
public static string BinPath
{
get
{
string binPath = AppDomain.CurrentDomain.BaseDirectory;
if (!binPath.Contains(@"\bin\", StringComparison.CurrentCultureIgnoreCase)
&& !binPath.EndsWith(@"\bin", StringComparison.CurrentCultureIgnoreCase))
{
binPath = Path.Combine(binPath, "bin");
//-- Please improve this if there is a better way
//-- Also note that apps like webapps do not have a debug or release folder. So we would just return bin.
#if DEBUG
if (Directory.Exists(Path.Combine(binPath, "Debug")))
binPath = Path.Combine(binPath, "Debug");
#else
if (Directory.Exists(Path.Combine(binPath, "Release")))
binPath = Path.Combine(binPath, "Release");
#endif
}
return binPath;
}
}
这么多年来,没有人真正提到过这一点。这是我从很棒的ApprovalTests项目中学到的技巧。诀窍在于使用程序集中的调试信息来查找原始目录。
在发布模式下,在启用优化的情况下,或者在与编译它的机器不同的机器上,这将不起作用。
但这将为您提供相对于您调用它的源代码文件的位置的路径
public static class PathUtilities
{
public static string GetAdjacentFile(string relativePath)
{
return GetDirectoryForCaller(1) + relativePath;
}
public static string GetDirectoryForCaller()
{
return GetDirectoryForCaller(1);
}
public static string GetDirectoryForCaller(int callerStackDepth)
{
var stackFrame = new StackTrace(true).GetFrame(callerStackDepth + 1);
return GetDirectoryForStackFrame(stackFrame);
}
public static string GetDirectoryForStackFrame(StackFrame stackFrame)
{
return new FileInfo(stackFrame.GetFileName()).Directory.FullName + Path.DirectorySeparatorChar;
}
}
博士tl;
程序集和DLL文件的概念是不同的。根据程序集的加载方式,路径信息会丢失或根本不可用。
不过,大多数情况下,提供的答案是有效的。
这个问题和前面的答案都有一个误解。在大多数情况下,提供的答案会工作得很好,但是
在某些情况下,无法获得当前代码所在程序集的正确路径。
程序集(包含可执行代码)和dll文件(包含程序集)的概念不是紧密耦合的。大会可以
来自一个DLL文件,但它不是必须的。
使用assembly . load (Byte[]) (MSDN)方法,可以直接从内存中的字节数组加载程序集。
字节数组来自哪里并不重要。它可以从文件中加载,从互联网上下载,动态生成……
下面是一个从字节数组加载程序集的示例。加载文件后,路径信息会丢失。这是不可能的
获取原始文件路径,之前描述的所有方法都不起作用。
此方法位于正在执行的程序集中,该程序集位于“D:/Software/DynamicAssemblyLoad/DynamicAssemblyLoad/bin/Debug/Runner.exe”
static void Main(string[] args)
{
var fileContent = File.ReadAllBytes(@"C:\Library.dll");
var assembly = Assembly.Load(fileContent);
// Call the method of the library using reflection
assembly
?.GetType("Library.LibraryClass")
?.GetMethod("PrintPath", BindingFlags.Public | BindingFlags.Static)
?.Invoke(null, null);
Console.WriteLine("Hello from Application:");
Console.WriteLine($"GetViaAssemblyCodeBase: {GetViaAssemblyCodeBase(assembly)}");
Console.WriteLine($"GetViaAssemblyLocation: {assembly.Location}");
Console.WriteLine($"GetViaAppDomain : {AppDomain.CurrentDomain.BaseDirectory}");
Console.ReadLine();
}
这个类位于Library.dll中:
public class LibraryClass
{
public static void PrintPath()
{
var assembly = Assembly.GetAssembly(typeof(LibraryClass));
Console.WriteLine("Hello from Library:");
Console.WriteLine($"GetViaAssemblyCodeBase: {GetViaAssemblyCodeBase(assembly)}");
Console.WriteLine($"GetViaAssemblyLocation: {assembly.Location}");
Console.WriteLine($"GetViaAppDomain : {AppDomain.CurrentDomain.BaseDirectory}");
}
}
为了完整起见,这里是GetViaAssemblyCodeBase()的实现,它对两个程序集都是相同的:
private static string GetViaAssemblyCodeBase(Assembly assembly)
{
var codeBase = assembly.CodeBase;
var uri = new UriBuilder(codeBase);
return Uri.UnescapeDataString(uri.Path);
}
Runner打印以下输出:
Hello from Library:
GetViaAssemblyCodeBase: D:/Software/DynamicAssemblyLoad/DynamicAssemblyLoad/bin/Debug/Runner.exe
GetViaAssemblyLocation:
GetViaAppDomain : D:\Software\DynamicAssemblyLoad\DynamicAssemblyLoad\bin\Debug\
Hello from Application:
GetViaAssemblyCodeBase: D:/Software/DynamicAssemblyLoad/DynamicAssemblyLoad/bin/Debug/Runner.exe
GetViaAssemblyLocation:
GetViaAppDomain : D:\Software\DynamicAssemblyLoad\DynamicAssemblyLoad\bin\Debug\
如您所见,代码基、位置或基目录都不正确。