是否有方法获取当前代码所在程序集的路径?我不需要调用程序集的路径,只需要包含代码的路径。

基本上,我的单元测试需要读取一些相对于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 () 给出与前面相同的结果。


当前回答

Web应用程序?

Server.MapPath("~/MyDir/MyFile.ext")

其他回答

博士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\

如您所见,代码基、位置或基目录都不正确。

我一直在用汇编。用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。

string path = Path.GetDirectoryName(typeof(DaoTests).Module.FullyQualifiedName);

我用这个来获取Bin目录的路径:

var i = Environment.CurrentDirectory.LastIndexOf(@"\");
var path = Environment.CurrentDirectory.Substring(0,i); 

你会得到这个结果:

“c: \ \ ricooley \文档\ visual studio用户 2010 \ \ Windows_Test_Project \ Windows_Test_Project \ bin项目”

与John的答案相同,但扩展方法略少啰嗦。

public static string GetDirectoryPath(this Assembly assembly)
{
    string filePath = new Uri(assembly.CodeBase).LocalPath;
    return Path.GetDirectoryName(filePath);            
}

现在你可以做:

var localDir = Assembly.GetExecutingAssembly().GetDirectoryPath();

或者如果你喜欢:

var localDir = typeof(DaoTests).Assembly.GetDirectoryPath();