Событие AssemblyResolve возникает при вызове Assembly.Load (byte ())
Итак, у меня есть проект WPF, в который входят библиотеки, которые используются другим проектом здесь, на моей работе. Это беспорядок зависимостей, я использую технику здесь: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.
Я пытался отцепить OnResolveAssembly до того, как я вызову Assembly.Load, но затем мое приложение умирает загадочной смертью, даже под 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;
}
Кажется, что теперь он работает нормально («сбойная» сборка будет нормально загружаться в моем втором фрагменте), но мне было бы интересно узнать, почему он не работает в первом.