我需要找到在托管代码执行开始组装。
// using System.Reflection;
Assembly entryAssembly = Assembly.GetEntryAssembly();
这似乎是要走的路,但对于MSDN参考页Assembly.GetEntryAssembly
指出,这种方法“[C]从非托管代码调用时返回NULL。”
在这种情况下,我想知道哪些组件是由非托管代码调用。
是否有这样做的一个可靠的方法,即一个总是返回一个非空Assembly
的参考?
我需要找到在托管代码执行开始组装。
// using System.Reflection;
Assembly entryAssembly = Assembly.GetEntryAssembly();
这似乎是要走的路,但对于MSDN参考页Assembly.GetEntryAssembly
指出,这种方法“[C]从非托管代码调用时返回NULL。”
在这种情况下,我想知道哪些组件是由非托管代码调用。
是否有这样做的一个可靠的方法,即一个总是返回一个非空Assembly
的参考?
我能想到的迄今最好的是下面的,应在单线程情况下工作:
// using System.Diagnostics;
// using System.Linq;
Assembly entryAssembly = new StackTrace().GetFrames().Last().GetMethod().Module.Assembly;
(以上代码段为了便于理解,而不是用于执行速度或存储器效率最优化。)
我想stakx的两种方法。
基于MainModule方法不起作用在某些特殊情况下(动态组件为例)。
基于堆栈跟踪方法可以在层次结构中返回一个组件太高(或低),如mscorlib程序。
我做了一点点变体在我的使用情况下效果很好:
// using System.Diagnostics;
// using System.Linq;
var methodFrames = new StackTrace().GetFrames().Select(t => t.GetMethod()).ToArray();
MethodBase entryMethod = null;
int firstInvokeMethod = 0;
for (int i = 0; i < methodFrames.Length; i++)
{
var method = methodFrames[i] as MethodInfo;
if (method == null)
continue;
if (method.IsStatic &&
method.Name == "Main" &&
(
method.ReturnType == typeof(void) ||
method.ReturnType == typeof(int) ||
method.ReturnType == typeof(Task) ||
method.ReturnType == typeof(Task<int>)
))
{
entryMethod = method;
}
else if (firstInvokeMethod == 0 &&
method.IsStatic &&
method.Name == "InvokeMethod" &&
method.DeclaringType == typeof(RuntimeMethodHandle))
{
firstInvokeMethod = i;
}
}
if (entryMethod == null)
entryMethod = firstInvokeMethod != 0 ? methodFrames[firstInvokeMethod - 1] : methodFrames.Last();
Assembly entryAssembly = entryMethod.Module.Assembly;
基本上,我走栈,直到我找到一种常规方法使用名为“主” void
或int
返回类型。 如果没有找到这样的方法,我期待通过反射调用的方法。 例如,NUnit的使用该调用加载单元测试。
当然,我这样做,只有当Assembly.GetEntryAssembly()
返回null
。
对于一个工作解决方案的另一个(主要是未经测试)的出发点可能是这样的:
// using System;
// using System.Diagnostics;
// using System.Linq;
ProcessModule mainModule = Process.GetCurrentProcess().MainModule;
Assembly entryAssembly = AppDomain.CurrentDomain.GetAssemblies()
.Single(assembly => assembly.Location == mainModule.FileName);
一些不确定性依然存在:
模块和组件是不一样的东西。 ProcessModule
甚至可能是从概念上不同的Module
。 将上面的代码始终在多模块(即多文件)组件的存在工作,特别是当程序集的入口点不在清单模块中?
被Process.MainModule
保证总是返回一个非空引用?