加载请求的程序集(即
ResolveEventArgs.RequestingAssembly
属性返回的程序集)时未加载上下文。
有关上下文的信息,请参阅
Assembly.LoadFrom(String)
方法重载。
可将同一程序集的多个版本加载到同一应用程序域中。 不推荐此做法,因为可能导致类型分配问题。 请参阅
适用于程序集加载的最佳做法
。
事件处理程序的禁忌操作
处理
AssemblyResolve
事件的主要规则是不应试图返回无法识别的程序集。 编写处理程序时应了解哪些程序集可能会导致引发该事件。 处理程序集应对其他程序集返回 null。
从 .NET Framework 4 开始,
AssemblyResolve
事件针对附属程序集引发。 此更改会影响为早期版本的 .NET Framework 编写的事件处理程序(如果此类事件处理程序尝试解决所有程序集加载请求)。 此更改不会影响忽略其无法识别的程序集的事件处理程序:此类处理程序返回
null
并遵循常规回退机制。
加载程序集时,事件处理程序禁止使用可导致递归引发
AssemblyResolve
事件的任何
AppDomain.Load
或
Assembly.Load
方法重载,因为可能导致堆栈溢出。 (请参阅本主题前面部分提供的列表。)即使为加载请求提供异常处理也会发生此情况,因为异常都是在所有事件处理程序返回后引发的。 因此,如果未找到
MyAssembly
,下面的代码将导致堆栈溢出:
using System;
using System.Reflection;
class BadExample
static void Main()
AppDomain ad = AppDomain.CreateDomain("Test");
ad.AssemblyResolve += MyHandler;
object obj = ad.CreateInstanceAndUnwrap(
"MyAssembly, version=1.2.3.4, culture=neutral, publicKeyToken=null",
"MyType");
catch (Exception ex)
Console.WriteLine(ex.Message);
static Assembly MyHandler(object source, ResolveEventArgs e)
Console.WriteLine("Resolving {0}", e.Name);
// DO NOT DO THIS: This causes a StackOverflowException
return Assembly.Load(e.Name);
/* This example produces output similar to the following:
Resolving MyAssembly, Version=1.2.3.4, Culture=neutral, PublicKeyToken=null
Resolving MyAssembly, Version=1.2.3.4, Culture=neutral, PublicKeyToken=null
Resolving MyAssembly, Version=1.2.3.4, Culture=neutral, PublicKeyToken=null
Resolving MyAssembly, Version=1.2.3.4, Culture=neutral, PublicKeyToken=null
Process is terminated due to StackOverflowException.
Imports System.Reflection
Class BadExample
Shared Sub Main()
Dim ad As AppDomain = AppDomain.CreateDomain("Test")
AddHandler ad.AssemblyResolve, AddressOf MyHandler
Dim obj As object = ad.CreateInstanceAndUnwrap(
"MyAssembly, version=1.2.3.4, culture=neutral, publicKeyToken=null",
"MyType")
Catch ex As Exception
Console.WriteLine(ex.Message)
End Try
End Sub
Shared Function MyHandler(ByVal source As Object, _
ByVal e As ResolveEventArgs) As Assembly
Console.WriteLine("Resolving {0}", e.Name)
// DO NOT DO THIS: This causes a StackOverflowException
Return Assembly.Load(e.Name)
End Function
End Class
' This example produces output similar to the following:
'Resolving MyAssembly, Version=1.2.3.4, Culture=neutral, PublicKeyToken=null
'Resolving MyAssembly, Version=1.2.3.4, Culture=neutral, PublicKeyToken=null
'Resolving MyAssembly, Version=1.2.3.4, Culture=neutral, PublicKeyToken=null
'Resolving MyAssembly, Version=1.2.3.4, Culture=neutral, PublicKeyToken=null
'Process is terminated due to StackOverflowException.
using namespace System;
using namespace System::Reflection;
ref class Example
internal:
static Assembly^ MyHandler(Object^ source, ResolveEventArgs^ e)
Console::WriteLine("Resolving {0}", e->Name);
// DO NOT DO THIS: This causes a StackOverflowException
return Assembly::Load(e->Name);
void main()
AppDomain^ ad = AppDomain::CreateDomain("Test");
ad->AssemblyResolve += gcnew ResolveEventHandler(&Example::MyHandler);
Object^ obj = ad->CreateInstanceAndUnwrap(
"MyAssembly, version=1.2.3.4, culture=neutral, publicKeyToken=null",
"MyType");
catch (Exception^ ex)
Console::WriteLine(ex->Message);
/* This example produces output similar to the following:
Resolving MyAssembly, Version=1.2.3.4, Culture=neutral, PublicKeyToken=null
Resolving MyAssembly, Version=1.2.3.4, Culture=neutral, PublicKeyToken=null
Resolving MyAssembly, Version=1.2.3.4, Culture=neutral, PublicKeyToken=null
Resolving MyAssembly, Version=1.2.3.4, Culture=neutral, PublicKeyToken=null
Process is terminated due to StackOverflowException.
处理 AssemblyResolve 的正确方法
从 AssemblyResolve 事件处理程序解析程序集时,如果处理程序使用 Assembly.Load 或 AppDomain.Load 方法调用,最终将触发 StackOverflowException。 而是要使用 LoadFile 或 LoadFrom 方法,因为这样不会引发 AssemblyResolve
事件。
假设 MyAssembly.dll
位于执行程序集附近的一个已知位置,在给定程序集路径的情况下可以使用 Assembly.LoadFile
来解析它。
using System;
using System.IO;
using System.Reflection;
class CorrectExample
static void Main()
AppDomain ad = AppDomain.CreateDomain("Test");
ad.AssemblyResolve += MyHandler;
object obj = ad.CreateInstanceAndUnwrap(
"MyAssembly, version=1.2.3.4, culture=neutral, publicKeyToken=null",
"MyType");
catch (Exception ex)
Console.WriteLine(ex.Message);
static Assembly MyHandler(object source, ResolveEventArgs e)
Console.WriteLine("Resolving {0}", e.Name);
var path = Path.GetFullPath("../../MyAssembly.dll");
return Assembly.LoadFile(path);
Imports System.IO
Imports System.Reflection
Class CorrectExample
Shared Sub Main()
Dim ad As AppDomain = AppDomain.CreateDomain("Test")
AddHandler ad.AssemblyResolve, AddressOf MyHandler
Dim obj As Object = ad.CreateInstanceAndUnwrap(
"MyAssembly, version=1.2.3.4, culture=neutral, publicKeyToken=null",
"MyType")
Catch ex As Exception
Console.WriteLine(ex.Message)
End Try
End Sub
Shared Function MyHandler(ByVal source As Object,
ByVal e As ResolveEventArgs) As Assembly
Console.WriteLine("Resolving {0}", e.Name)
Dim fullPath = Path.GetFullPath("../../MyAssembly.dll")
Return Assembly.LoadFile(fullPath)
End Function
End Class
using namespace System;
using namespace System::IO;
using namespace System::Reflection;
ref class Example
internal:
static Assembly^ MyHandler(Object^ source, ResolveEventArgs^ e)
Console::WriteLine("Resolving {0}", e->Name);
String^ fullPath = Path::GetFullPath("../../MyAssembly.dll");
return Assembly::LoadFile(fullPath);
void main()
AppDomain^ ad = AppDomain::CreateDomain("Test");
ad->AssemblyResolve += gcnew ResolveEventHandler(&Example::MyHandler);
Object^ obj = ad->CreateInstanceAndUnwrap(
"MyAssembly, version=1.2.3.4, culture=neutral, publicKeyToken=null",
"MyType");
catch (Exception^ ex)
Console::WriteLine(ex->Message);
适用于程序集加载的最佳做法
使用应用程序域