C#获取调用程序集的父程序集名称

我有一个我正在研究的C#unit testing应用程序。 涉及三个程序集 – C#app本身的程序集,应用程序使用的第二个程序集,以及第二个程序集使用的第三个程序集。

所以这些电话是这样的:

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

我需要在第三个程序集中执行的操作是获取调用第二个程序集的Fist程序集的名称。

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

返回第二个程序集的名称。 和

 Assembly.GetEntryAssembly().ManifestModule.Name 

返回NULL

有没有人知道是否有办法获得第一届大会的集会名称?

根据其他用户的需求,我把代码放在这里。 这不是100%的代码,而是遵循这样的代码。

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

和测试项目方法

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

我想你应该能够这样做:

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

这将使您获得包含第一个在当前线程中首次启动的方法的程序集。 因此,如果您不在主线程中,这可能与EntryAssembly不同,如果我理解您的情况,那么这应该是您正在寻找的程序集。

你也可以得到实际的Assembly而不是这样的名字:

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

编辑 – 截至2015年9月23日

请注意

 GetMethod().ReflectedType 

可以为null,因此检索其AssemblyQualifiedName可能会引发exception。 例如,如果想要检查仅专用于ORM(如linq2db等等)POCO类的vanilla c.tor,那就很有趣。

这将返回引用currentAsembly的初始Assembly。

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

如果你也从nunit-console运行测试, Assembly.GetEntryAssembly()为null。

如果您只想要执行应用程序的名称,请使用:

  System.Diagnostics.Process.GetCurrentProcess().ProcessName 

要么

  Environment.GetCommandLineArgs()[0]; 

对于nunit-console,您将分别获得“nunit-console”和“C:\ Program Files \ NUnit 2.5.10 \ bin \ net-2.0 \ nunit-console.exe”。

如果您需要找到顶部组件,无论调用顺序如何,您都可以使用

  Assembly.GetEntryAssembly() 

它对我有用:

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

尝试:

 Assembly.GetEntryAssembly().ManifestModule.Name 

这应该是实际执行以启动进程的程序集。

Assembly.GetEntryAssembly()怎么样? 它返回进程的主要可执行文件。

Process.GetCurrentProcess().MainModule.ModuleName也应该返回与ManifestModule名称(“yourapp.exe”)大致相同的内容。

不完全确定你在寻找什么,尤其是当你在unit testing的环境中运行时,你最终会得到:

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

(或类似的东西,取决于你的测试运行器)在导致任何方法被调用的程序集中。

以下代码打印调用中涉及的每个程序集的名称。

 var trace = new StackTrace(); var assemblies = new List(); 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); } 

如果知道堆栈中的帧数,则可以使用StackFrame对象并跳过前一帧的数量。

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

但是,如果你想要第一个电话,你需要获得所有帧并采取第一个。 (见AVee解决方案)

这适用于在NUnit测试中使用两个程序集时获取原始程序集,而不返回NULL。 希望这可以帮助。

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