我有一个WPF项目,它正在调用另一个项目中使用的dll。这是一个依赖关系的混乱,我一直在使用这里的技术: http://www.digitallycreated.net/Blog/61/combining-multiple-assemblies-into-a-single-exe-for-a-wpf-application将依赖项嵌入到单个可执行文件中。
现在,当我调用其中一个依赖项中的特定方法时,我遇到了AssemblyResolve事件。我的OnResolveAssembly事件运行,它将该程序集作为嵌入资源找到(很酷!),并执行“return Assembly.Load(assembyRawBytes)”。如果我此时按F11(在OnResolveAssembly开头处设置断点),我会得到另一个对同一事件的调用。它也是针对同一程序集的(args.Name相同)。
如果我让它运行,我就会遇到堆栈溢出,因为我似乎永远无法逃脱这个递归事件调用。
MSDN文档并没有真正说明Assembly.Load何时会失败,除了FileNotFoundException或BadImageFormatException。
我尝试在调用Assembly.Load之前取消挂接OnResolveAssembly,但是我的应用程序突然死亡了,即使在VS下也只是消失了。
我可能违反了几个规则,但是欢迎提供一些问题查找的起点。
我要开始搜索有问题的DLL,看看是否有关于它出现问题的线索(也许它是混合程序集?)。
这是我的OnResolveAssembly处理程序:
现在,当我调用其中一个依赖项中的特定方法时,我遇到了AssemblyResolve事件。我的OnResolveAssembly事件运行,它将该程序集作为嵌入资源找到(很酷!),并执行“return Assembly.Load(assembyRawBytes)”。如果我此时按F11(在OnResolveAssembly开头处设置断点),我会得到另一个对同一事件的调用。它也是针对同一程序集的(args.Name相同)。
如果我让它运行,我就会遇到堆栈溢出,因为我似乎永远无法逃脱这个递归事件调用。
MSDN文档并没有真正说明Assembly.Load何时会失败,除了FileNotFoundException或BadImageFormatException。
我尝试在调用Assembly.Load之前取消挂接OnResolveAssembly,但是我的应用程序突然死亡了,即使在VS下也只是消失了。
我可能违反了几个规则,但是欢迎提供一些问题查找的起点。
我要开始搜索有问题的DLL,看看是否有关于它出现问题的线索(也许它是混合程序集?)。
这是我的OnResolveAssembly处理程序:
private static Assembly OnResolveAssembly(object sender, ResolveEventArgs args)
{
Assembly executingAssembly = Assembly.GetExecutingAssembly();
AssemblyName assemblyName = new AssemblyName(args.Name);
string path = assemblyName.Name + ".dll";
if (assemblyName.CultureInfo.Equals(System.Globalization.CultureInfo.InvariantCulture) == false)
{
path = String.Format(@"{0}\{1}", assemblyName.CultureInfo, path);
}
using (Stream stream = executingAssembly.GetManifestResourceStream(path))
{
if (stream == null)
return null;
byte[] assemblyRawBytes = new byte[stream.Length];
stream.Read(assemblyRawBytes, 0, assemblyRawBytes.Length);
assemblyDictionary.Add(assemblyName.Name, Assembly.Load(assemblyRawBytes));
return assemblyDictionary[assemblyName.Name];
}
}
目前,我通过遍历所有资源并尝试使用Assembly.Load加载它们,然后将它们存储在字典中以便检索(在OnResolveAssembly事件期间)来解决这个问题:
[STAThread]
public static void Main()
{
AppDomain.CurrentDomain.AssemblyResolve += OnResolveAssembly;
Assembly executingAssembly = Assembly.GetExecutingAssembly();
string[] resources = executingAssembly.GetManifestResourceNames();
foreach (string resource in resources)
{
if (resource.EndsWith(".dll"))
{
using (Stream stream = executingAssembly.GetManifestResourceStream(resource))
{
if (stream == null)
continue;
byte[] assemblyRawBytes = new byte[stream.Length];
stream.Read(assemblyRawBytes, 0, assemblyRawBytes.Length);
try
{
assemblyDictionary.Add(resource, Assembly.Load(assemblyRawBytes));
}
catch (Exception ex)
{
System.Diagnostics.Debug.Print("Failed to load: " + resource + " Exception: " + ex.Message);
}
}
}
}
App.Main();
}
private static Assembly OnResolveAssembly(object sender, ResolveEventArgs args)
{
Assembly executingAssembly = Assembly.GetExecutingAssembly();
AssemblyName assemblyName = new AssemblyName(args.Name);
string path = assemblyName.Name + ".dll";
if (assemblyDictionary.ContainsKey(path))
{
return assemblyDictionary[path];
}
return null;
}
现在它似乎工作正常了(“失败”的组件在我的第二个片段中可以正常加载),但我很想知道为什么它在第一个片段中不起作用。
Assembly.Load(byte[])
ж—¶и§ҰеҸ‘AssemblyResolve
еҗ—пјҹиҝҷжӯЈжҳҜжҲ‘еңЁиҝҷйҮҢеҜ»жүҫзҡ„жғ…еҶөпјҢдҪҶжҲ‘ж— жі•жһ„е»әиҝҷж ·зҡ„зӨәдҫӢгҖӮдҪ иғҪжҸҗдҫӣжӣҙеӨҡз»ҶиҠӮеҗ—пјҹи°ўи°ўгҖӮ - Vladimir Reshetnikov