我需要一个永远不会返回null的`Assembly.GetEntryAssembly()`的替代品
我需要找到托管代码执行开始的程序集。
// using System.Reflection; Assembly entryAssembly = Assembly.GetEntryAssembly();
这似乎是要走的路,但Assembly.GetEntryAssembly
的MSDN参考页指出此方法“[c]从非托管代码调用时返回null。”
在这种情况下,我想知道哪个程序集是由非托管代码调用的。
有没有一种可靠的方法,即总是返回非空的Assembly
引用?
到目前为止,我能想到的最好的是以下内容,它应该在单线程场景中工作:
// using System.Diagnostics; // using System.Linq; Assembly entryAssembly = new StackTrace().GetFrames().Last().GetMethod().Module.Assembly;
(上面的代码片段经过优化,易于理解,而不是执行速度或内存效率。)
我尝试了两种stakx方法。
基于MainModule的方法在某些特殊情况下不起作用(例如动态程序集)。
基于StackTrace的方法可以在层次结构中返回过高(或低)的程序集,如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.Name == "Main" && method.ReturnType == typeof(void)) entryMethod = method; else if (firstInvokeMethod == 0 && method.Name == "InvokeMethod" && method.IsStatic && method.DeclaringType == typeof(RuntimeMethodHandle)) firstInvokeMethod = i; } if (entryMethod == null) entryMethod = firstInvokeMethod != 0 ? methodFrames[firstInvokeMethod - 1] : methodFrames.Last(); Assembly entryAssembly = entryMethod.Module.Assembly;
基本上,我走了堆栈,直到找到一个名为“Main”的传统方法,返回类型为void
。 如果没有找到这样的方法,我会寻找通过reflection调用的方法。 例如,NUnit使用该调用来加载unit testing。
当然,我只有在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);
一些不确定因素依旧:
上述就是C#学习教程:我需要一个永远不会返回null的`Assembly.GetEntryAssembly()`的替代品分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注---计算机技术网(www.ctvol.com)
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请点击右边联系管理员删除。
如若转载,请注明出处:https://www.ctvol.com/cdevelopment/1016271.html