type - working with reflection in c#




Como obtenho o caminho da montagem em que o código está? (18)

É tão simples assim:

var dir = AppDomain.CurrentDomain.BaseDirectory;

Existe uma maneira de obter o caminho para o assembly no qual o código atual reside? Eu não quero o caminho do assembly de chamada, apenas o que contém o código.

Basicamente, meu teste de unidade precisa ler alguns arquivos de teste xml que estão localizados em relação à dll. Eu quero o caminho para sempre resolver corretamente, independentemente de se a dll de teste é executada a partir de TestDriven.NET, a GUI MbUnit ou outra coisa.

Edit : As pessoas parecem estar entendendo mal o que estou pedindo.

Minha biblioteca de teste está localizada em digamos

C: \ projetos \ myapplication \ daotests \ bin \ Debug \ daotests.dll

e gostaria de obter este caminho:

C: \ projetos \ myapplication \ daotests \ bin \ Debug \

As três sugestões até agora falharam quando eu fugi do MbUnit Gui:

  • Environment.CurrentDirectory fornece c: \ Program Files \ MbUnit

  • System.Reflection.Assembly.GetAssembly(typeof(DaoTests)).Location fornece C: \ Documents and Settings \ george \ Configurações Locais \ Temp \ .... \ DaoTests.dll

  • System.Reflection.Assembly.GetExecutingAssembly().Location dá o mesmo que o anterior.


A única solução que funcionou para mim ao usar compartilhamentos CodeBase e UNC Network foi:

System.IO.Path.GetDirectoryName(new System.Uri(System.Reflection.Assembly.GetExecutingAssembly().CodeBase).LocalPath);

Também funciona com URIs normais também.


Aqui está uma porta VB.NET do código de John Sibly. O Visual Basic não faz distinção entre maiúsculas e minúsculas, portanto, alguns dos nomes de variáveis ​​dele estavam colidindo com nomes de tipos.

Public Shared ReadOnly Property AssemblyDirectory() As String
    Get
        Dim codeBase As String = Assembly.GetExecutingAssembly().CodeBase
        Dim uriBuilder As New UriBuilder(codeBase)
        Dim assemblyPath As String = Uri.UnescapeDataString(uriBuilder.Path)
        Return Path.GetDirectoryName(assemblyPath)
    End Get
End Property

Em todos esses anos, ninguém mencionou este aqui. Um truque que aprendi com o incrível projeto ApprovalTests . O truque é que você usa as informações de depuração no assembly para encontrar o diretório original.

Isso não funcionará no modo RELEASE, nem com otimizações ativadas, nem em uma máquina diferente da que foi compilada.

Mas isso vai te dar caminhos que são relativos à localização do arquivo de código-fonte que você chama de

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;
    }
}

Eu defini a propriedade a seguir, pois usamos isso frequentemente em testes unitários.

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);
    }
}

A propriedade Assembly.Location , às vezes, fornece alguns resultados engraçados ao usar o NUnit (onde os assemblies são executados a partir de uma pasta temporária), portanto, prefiro usar CodeBase que fornece o caminho no formato URI, e UriBuild.UnescapeDataString remove o File:// o início e GetDirectoryName altera para o formato normal do windows.


Eu suspeito que o problema real aqui é que o seu corredor de teste está copiando seu assembly para um local diferente. Não há como, em tempo de execução, dizer onde o assembly foi copiado, mas você pode provavelmente inverter um switch para dizer ao executor de teste para executar o assembly de onde ele está e não copiá-lo para um diretório de sombra.

Tal mudança provavelmente será diferente para cada corredor de teste, é claro.

Você já pensou em incorporar seus dados XML como recursos dentro do seu assembly de teste?


Eu tenho usado Assembly.CodeBase em vez de 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("/", "\\");

Está funcionando, mas não tenho mais certeza se está 100% correto. A página em http://blogs.msdn.com/suzcook/archive/2003/06/26/assembly-codebase-vs-assembly-location.aspx diz:

"O CodeBase é um URL para o local onde o arquivo foi encontrado, enquanto o Local é o caminho onde ele foi realmente carregado. Por exemplo, se o assembly foi baixado da Internet, seu CodeBase pode iniciar com" http: // " , mas sua localização pode começar com "C: \". Se o arquivo foi copiado na sombra, o local seria o caminho para a cópia do arquivo no diretório da cópia de sombra. Também é bom saber que a CodeBase não é garantida a ser configurado para montagens no GAC. No entanto, o local sempre será definido para montagens carregadas do disco. "

Você pode querer usar CodeBase em vez de Location.


Eu uso isso para obter o caminho para o diretório Bin:

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

Você obtém este resultado:

"c: \ users \ ricooley \ documentos \ visual studio 2010 \ Projetos \ Windows_Test_Project \ Windows_Test_Project \ bin"


Isso ajuda?

//get the full location of the assembly with DaoTests in it
string fullPath = System.Reflection.Assembly.GetAssembly(typeof(DaoTests)).Location;

//get the folder that's in
string theDirectory = Path.GetDirectoryName( fullPath );

Isso deve funcionar, a menos que o assembly seja copiado em sombra :

string path = System.Reflection.Assembly.GetExecutingAssembly().Location

O diretório atual onde você existe.

Environment.CurrentDirectory;  // This is the current directory of your application

Se você copiar o arquivo .xml com a compilação, deverá encontrá-lo.

ou

System.Reflection.Assembly assembly = System.Reflection.Assembly.GetAssembly(typeof(SomeObject));

// The location of the Assembly
assembly.Location;

O mesmo que a resposta de John, mas um método de extensão ligeiramente menos detalhado.

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

Agora você pode fazer:

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

ou se preferir:

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

Que tal agora ...

string ThisdllDirectory = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);

Então apenas cortar o que você não precisa


Tanto quanto eu posso dizer, a maioria das outras respostas tem alguns problemas.

A maneira correta de fazer isso para um assembly não baseado em disco (em oposição a baseado na Web) é utilizar a propriedade CodeBase do assembly atualmente em execução.

Isso retorna um URL ( file:// ). Em vez de mexer com manipulação de seqüência de caracteres ou UnescapeDataString , isso pode ser convertido com o mínimo de confusão, aproveitando a propriedade LocalPath do Uri .

var codeBaseUrl = Assembly.GetExecutingAssembly().CodeBase;
var filePathToCodeBase = new Uri(codeBaseUrl).LocalPath;
var directoryPath = Path.GetDirectoryName(filePathToCodeBase);

Você obterá um diretório incorreto se um caminho contiver o símbolo '#'. Então eu uso uma modificação da resposta do John Sibly que é a combinação UriBuilder.Path e UriBuilder.Fragment:

public static string AssemblyDirectory
{
    get
    {
        string codeBase = Assembly.GetExecutingAssembly().CodeBase;
        UriBuilder uri = new UriBuilder(codeBase);
        //modification of the John Sibly answer    
        string path = Uri.UnescapeDataString(uri.Path.Replace("/", "\\") + 
          uri.Fragment.Replace("/", "\\"));
        return Path.GetDirectoryName(path);
     }
}

Você pode obter o caminho bin por AppDomain.CurrentDomain.RelativeSearchPath


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

var assembly = System.Reflection.Assembly.GetExecutingAssembly();
var assemblyPath = assembly.GetFiles()[0].Name;
var assemblyDir = System.IO.Path.GetDirectoryName(assemblyPath);




reflection