Использование сборки resolve для обработки отсутствующих сборок в C#
Я следую способ 3 в http://support.microsoft.com/kb/837908 для динамической загрузки сборок в C#. Тем не менее, код не работает для меня. В следующем разделе кода автор загружает отсутствующую сборку, только если имя отсутствующей сборки является одной из сборок, на которые ссылается приложение.
Когда я запускаю это в режиме отладки, вызывается функция, но отсутствующая сборка отсутствует ни в одной из упомянутых сборок, и поэтому она не установлена в моем случае. Есть идеи, почему это происходит? Я не уверен, что это DLL C# или родной C++. Может ли это быть из-за того, что библиотеки C++ не могут быть загружены таким образом? Тогда почему эта функция вызывается для отсутствующей сборки C++? Любые объяснения приветствуются. Если это не работает для сборок C++, на которые ссылается C#, каковы альтернативы?
private Assembly MyResolveEventHandler(object sender,ResolveEventArgs args)
{
//This handler is called only when the common language runtime tries to bind to the assembly and fails.
//Retrieve the list of referenced assemblies in an array of AssemblyName.
Assembly MyAssembly,objExecutingAssemblies;
string strTempAssmbPath="";
objExecutingAssemblies=Assembly.GetExecutingAssembly();
AssemblyName [] arrReferencedAssmbNames=objExecutingAssemblies.GetReferencedAssemblies();
//Loop through the array of referenced assembly names.
foreach(AssemblyName strAssmbName in arrReferencedAssmbNames)
{
//Check for the assembly names that have raised the "AssemblyResolve" event.
if(strAssmbName.FullName.Substring(0, strAssmbName.FullName.IndexOf(","))==args.Name.Substring(0, args.Name.IndexOf(",")))
{
//Build the path of the assembly from where it has to be loaded.
strTempAssmbPath="C:\\Myassemblies\\"+args.Name.Substring(0,args.Name.IndexOf(","))+".dll";
break;
}
}
//Load the assembly from the specified path.
MyAssembly = Assembly.LoadFrom(strTempAssmbPath);
//Return the loaded assembly.
return MyAssembly;
}
1 ответ
Термин "сборка" не означает просто какую-либо DLL; это означает, что DLL создана с использованием и для.NET. Его также часто называют "управляемым кодом", что примерно означает, что вы используете сборщик мусора.NET вместо обычной кучи C++ для управления памятью. (Я упрощаю. Существуют также "сборки в смешанном режиме", которые разрешаются таким образом, хотя в них используется сочетание управляемого и неуправляемого кода. И "управляемый" означает нечто большее, чем просто управление памятью.)
Не имеет значения, написана ли ваша ссылочная сборка на C++/CLI или на C#. C++/CLI часто путают с C++, но на самом деле это другой язык с дополнительными возможностями для использования преимуществ управляемой среды. Если вы компилируете что-то C++ с помощью /clr
переключатель, это C++/CLI, а не C++.
Есть три ошибки с ссылочной статьей базы знаний, которые вам нужно понять.
"Метод 3" в статье не учитывает сборки с косвенной ссылкой. То есть сборки, на которые ссылаются сборки, на которые ссылается ваша основная сборка. Это, вероятно, кусает тебя прямо сейчас.
В статье не упоминается, что очень важно, чтобы вы сделали как можно меньше в теле метода, который регистрирует ваш обработчик, или джиттер разрешит некоторые сборки до того, как ваш обработчик будет зарегистрирован - даже если строки кода, ответственные за это, приведены ниже регистрация по тому же методу. Это потому, что JIT-компиляция предшествует выполнению.
Если вы имеете дело с кодом C++/CLI, скорее всего, вам также потребуется загрузить некоторые неуправляемые библиотеки DLL C++, на которые ссылалась предыдущая. Это делается с использованием традиционного порядка поиска Windows DLL вне вашего резольвера. Но это не ваша проблема, если вы видите обработчик, введенный для конкретной DLL. Обычный тип C или C++ DLL, который не имеет ничего общего с.NET, вообще не будет виден в обработчике.