从 StackTrace 获取调用程序集





5.00/5 (2投票s)
本文介绍了一种从被调用程序集获取调用测试程序集的便捷方法
引言
最近,我在开发一个类库时,该类库预计会被基于 NUnit 的一些测试库调用。在被调用库的 `static` 构造函数中实现了一些代码,用于解析测试库的类型,因此被调用函数首先需要知道外部调用程序集。
然而,Assembly.GetCallingAssembly() 总是会返回被调用库本身,因为 `static` 构造函数会在类的实例化之前自动调用。而 Assembly.GetEntryAssembly() 总是会返回 null
,这可能是因为执行代码是由 NUnit 框架启动的。看来我需要将代码移动到调用测试库中,或者更改其背后的逻辑。
幸运的是,我注意到在 Visual Studio 的“调用堆栈”窗口中,调用序列非常清晰,所以我尝试使用 StackTrace 并获得了预期的结果。虽然这种方法很简单,但我在网上没有找到相关的讨论,所以可能其他人阅读这篇文章后可以节省时间来解决这个问题。
详细说明
获取调用程序集的代码非常简单
using System.Diagnostics;
using System.Reflection;
private static Assembly callingAssemblyByStackTrace()
{
Assembly thisAssembly = Assembly.GetExecutingAssembly();
StackTrace stackTrace = new StackTrace();
StackFrame[] frames = stackTrace.GetFrames();
foreach (var stackFrame in frames)
{
var ownerAssembly = stackFrame.GetMethod().DeclaringType.Assembly;
if (ownerAssembly != thisAssembly)
return ownerAssembly;
}
return thisAssembly;
}
此方法有意放置在 `static` 构造函数之外,如下所示
public class Class1
{
private static Assembly callingAssemblyByStackTrace(){}
static Class1()
{
Console.WriteLine("Assembly.GetExecutingAssembly() returns: " +
Assembly.GetExecutingAssembly());
Console.WriteLine("Assembly.GetEntryAssembly() returns: " + Assembly.GetEntryAssembly());
Console.WriteLine("Assembly.GetCallingAssembly() returns: " +
Assembly.GetCallingAssembly());
Assembly callingAssembly = callingAssemblyByStackTrace();
Console.WriteLine("The calling Assembly is " + callingAssembly);
}
public Class1(){}
}
为了测试其功能,还有一个类库类型的项目引用了上述程序集和 NUnit,如下所示
[TestFixture]
public class TestClass
{
[Test]
public void Test1()
{
Class1 class1 = new Class1();
}
}
因此,由 NUnit 运行的测试代码会实例化一个 Class1
对象,这将触发 static Class1()
,后者会调用 callingAssemblyByStackTrace()
来获取输出
Assembly.GetExecutingAssembly() returns: AssemblyFromStackTrace,
Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
Assembly.GetEntryAssembly() returns:
Assembly.GetCallingAssembly() returns: AssemblyFromStackTrace,
Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
The calling Assembly is AssemblyFromStackTraceTest,
Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
AssemblyFromStackTraceTest
正是我所期望的。
Using the Code
压缩文件包含两个项目,将两者提取到一个文件夹中。AssemblyFromStackTraceTest
需要引用 AssemblyFromStackTrace
项目和 NUnit,运行它作为测试,就可以在控制台中看到上述输出。