web-dev-qa-db-fra.com

C # Obtention de l'assembly parent Nom de l'assembly appelant

J'ai une application de test d'unité C # sur laquelle je travaille. Trois assemblées sont impliquées: l’assemblée de l’application C # elle-même, une deuxième assemblée utilisée par l’application et une troisième assemblée utilisée par la deuxième.

Donc, les appels vont comme ceci:

First Assembly ------> Second Assembly---------> Third Assembly.

Ce que je dois faire à la troisième assemblée, c’est obtenir le nom de la première assemblée qui a convoqué la deuxième assemblée.

Assembly.GetExecutingAssembly().ManifestModule.Name
Assembly.GetCallingAssembly().ManifestModule.Name

renvoie le nom de la deuxième assemblée. et 

Assembly.GetEntryAssembly().ManifestModule.Name

retourne NULL

Est-ce que quelqu'un sait s'il existe un moyen d'obtenir le nom de l'Assemblée de la première assemblée? 

Selon la demande des autres utilisateurs, je mets le code ici. Ce n'est pas un code à 100% mais un code comme celui-ci.

namespace FirstAssembly{
public static xcass A
{
        public static Stream OpenResource(string name)
        {
            return Reader.OpenResource(Assembly.GetCallingAssembly(), ".Resources." + name);
        }
}
}

using FirstAssembly;
namespace SecondAssembly{
public static class B 

{
public static Stream FileNameFromType(string Name)

{
return = A.OpenResource(string name);
}
}
}

et méthode de projet d'essai

using SecondAssembly;
namespace ThirdAssembly{
public class TestC
{

 [TestMethod()]
        public void StremSizTest()
        {
            // ARRANGE
            var Stream = B.FileNameFromType("ValidMetaData.xml");
            // ASSERT
            Assert.IsNotNull(Stream , "The Stream  object should not be null.");
        }
}
}
30
Saroop Trivedi

Je suppose que vous devriez pouvoir le faire comme ceci:

using System.Diagnostics;
using System.Linq;

...

StackFrame[] frames = new StackTrace().GetFrames();
string initialAssembly = (from f in frames 
                          select f.GetMethod().ReflectedType.AssemblyQualifiedName
                         ).Distinct().Last();

Cela vous donnera l'assembly qui contient la première méthode qui a été démarrée pour la première fois dans le thread actuel. Donc, si vous n'êtes pas dans le fil principal, cela peut être différent de EntryAssembly, si je comprends bien votre situation, il devrait s'agir de l'Assemblée que vous recherchez.

Vous pouvez également obtenir l’assemblée réelle au lieu du nom suivant:

Assembly initialAssembly = (from f in frames 
                          select f.GetMethod().ReflectedType.Assembly
                         ).Distinct().Last();

Edit - à partir du 23 septembre 2015

S'il vous plaît, notez que 

GetMethod().ReflectedType

peut être null, ainsi récupérer son AssemblyQualifiedName pourrait générer une exception . Par exemple, c'est intéressant si on veut vérifier un c.tor Vanilla dédié uniquement à un ORM (comme linq2db, etc ...) classe POCO.

29
AVee

Cela renverra l'assembly initial qui référence votre currentAssembly.

var currentAssembly = Assembly.GetExecutingAssembly();
var callerAssemblies = new StackTrace().GetFrames()
            .Select(x => x.GetMethod().ReflectedType.Assembly).Distinct()
            .Where(x => x.GetReferencedAssemblies().Any(y => y.FullName == currentAssembly.FullName));
var initialAssembly = callerAssemblies.Last();
11
realstrategos

Assembly.GetEntryAssembly () est nul si vous exécutez des tests à partir de nunit-console aussi. 

Si vous voulez juste le nom de l'application en cours d'exécution, utilisez:

 System.Diagnostics.Process.GetCurrentProcess().ProcessName 

ou

 Environment.GetCommandLineArgs()[0];

Pour nunit-console , vous obtiendrez respectivement "nunit-console" et "C:\Program Files\NUnit 2.5.10\bin\net-2.0\nunit-console.exe".

6
tymtam

Cela a fonctionné pour moi en utilisant ceci:

System.Reflection.Assembly.GetEntryAssembly().GetName()
5
Marcello

Si vous devez trouver l’Assemblée supérieure, quel que soit l’ordre dans lequel vous appelez, vous pouvez utiliser 

   Assembly.GetEntryAssembly()
4
Me.Name

Vous n'êtes pas tout à fait sûr de ce que vous recherchez, d'autant plus que, dans le contexte d'un test unitaire, vous obtiendrez:

mscorlib.dll
Microsoft.VisualStudio.TestPlatform.Extensions.VSTestIntegration.dll

(ou quelque chose de similaire en fonction de votre testeur) dans l’ensemble des assemblys qui permettent d’appeler une méthode.

Le code ci-dessous imprime le nom de chacun des assemblys impliqués dans l'appel.

var trace = new StackTrace();
var assemblies = new List<Assembly>();
var frames = trace.GetFrames();

if(frames == null)
{
    throw new Exception("Couldn't get the stack trace");
}

foreach(var frame in frames)
{
    var method = frame.GetMethod();
    var declaringType = method.DeclaringType;

    if(declaringType == null)
    {
        continue;
    }

    var Assembly = declaringType.Assembly;
    var lastAssembly = assemblies.LastOrDefault();

    if(Assembly != lastAssembly)
    {
        assemblies.Add(Assembly);
    }
}

foreach(var Assembly in assemblies)
{
    Debug.WriteLine(Assembly.ManifestModule.Name);
}
0
mlorbetske

Si vous connaissez le nombre d'images dans la pile, vous pouvez utiliser l'objet StackFrame et ignorer le nombre d'images précédentes.

// You skip 2 frames
System.Diagnostics.StackFrame stack = new System.Diagnostics.StackFrame(2, false);
string assemblyName = stack.GetMethod().DeclaringType.AssemblyQualifiedName;

Mais si vous voulez le premier appel, vous devez obtenir toutes les images et prendre le premier. (voir solution AVee)

0
Hyralex

Que diriez-vous de Assembly.GetEntryAssembly() ? Il retourne l'exécutable principal du processus. 

Process.GetCurrentProcess().MainModule.ModuleName devrait également renvoyer à peu près le même nom que le nom ManifestModule ("yourapp.exe"). 

0
Botz3000

Essayer:

Assembly.GetEntryAssembly().ManifestModule.Name

Cela devrait être l'assembly qui a été réellement exécuté pour démarrer votre processus.

0
Jon Egerton