Использование assemblyresolve для обработки отсутствующих сборок в С#
Я следую методу 3 в http://support.microsoft.com/kb/837908, чтобы динамически загружать сборки в С#. Однако код для меня не работает. В следующем разделе кода автор загружает недостающую сборку только в том случае, если имя отсутствующей сборки является одной из сборок, на которые ссылается приложение.
Когда я запускаю это при отладке, функция вызывается, но недостающая сборка не входит ни в одну из этих ссылок, и поэтому она не задана в моем случае. Любые идеи, почему это происходит? Я не уверен, что эта DLL является С# или родным С++. Может ли это быть, потому что С++ dll не могут быть загружены таким образом? Тогда почему эта функция вызывается для отсутствующей сборки С++? Любые объяснения оцениваются. Если это не работает для сборок С++, на которые ссылаются С#, какие альтернативы?
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. Его также часто называют "управляемым кодом", который примерно означает, что вы используете сборщик мусора .NET, а не обычную кучу С++ для управления памятью. (Я упрощаю, есть также "сборки смешанного режима", которые разрешаются таким образом, хотя они используют сочетание управляемого и неуправляемого кода. И "управляемый" означает совсем немного больше, чем просто управление памятью.)
Не имеет значения, написана ли ваша ссылка на сборку на С++/CLI или на С#. С++/CLI часто путают с С++, но на самом деле это другой язык с дополнительными возможностями для использования управляемой среды. Если вы скомпилируете что-то С++ 'ish с помощью переключателя /clr
, это С++/CLI, а не С++.
Есть три исправления с указанной статьей базы знаний, которые вам нужно понять.
-
"Метод 3" в статье не учитывает косвенные ссылки. То есть сборки, на которые ссылаются узлы, ссылающиеся на вашу основную сборку. Это, вероятно, укусит вас прямо сейчас.
-
В статье не упоминается, что крайне важно, чтобы вы делали как можно меньше в теле метода, который регистрирует ваш обработчик, или джиттер разрешит некоторые сборки до того, как ваш обработчик зарегистрирован, даже если код строки, отвечающие за это, ниже регистрации в том же методе. Это связано с тем, что компиляция JIT предшествует исполнению.
-
Если вы имеете дело с кодом С++/CLI, вероятность того, что вам также нужно загрузить некоторые неуправляемые DLL на С++, с которыми была связана предыдущая ссылка. Это делается с использованием обычного порядка поиска Windows DLL и вне вашего резольвера. Но это не ваша проблема, пока вы видите, что обработчик введен для конкретной DLL. Нормальный тип C или С++ DLL, который не имеет ничего общего с .NET, вообще не будет отображаться в обработчике.