Compartilhar via


Resolvendo as cargas de Assembly

A.NET Framework fornece a AppDomain.AssemblyResolve evento para aplicativos que exigem maior controle sobre o carregamento do assembly. Por tratamento desse evento, seu aplicativo pode carregar um assembly em que o contexto de carregamento de fora os caminhos probing normais, selecionados qual das várias versões do assembly para carregar, emitir um assembly dinâmico e retorná-lo e assim por diante. Este tópico fornece diretrizes para manipulação de AssemblyResolve de evento.

Observação

Para resolver as cargas de assembly no contexto somente de reflexão, use o AppDomain.ReflectionOnlyAssemblyResolve eventos em vez disso.

Como funciona o evento AssemblyResolve

Quando você registra um manipulador para o AssemblyResolve o manipulador de evento é chamado sempre que o tempo de execução falha vincular a um assembly por nome. Por exemplo, chamar os métodos a seguir do código do usuário pode fazer com que o AssemblyResolve evento a ser gerado:

O que faz o manipulador de eventos

O manipulador para o AssemblyResolve evento recebe o nome de exibição do assembly para ser carregado na ResolveEventArgs.Name propriedade. Se o manipulador não reconhecer o nome do assembly, retorna null (Nothing em Visual Basic, nullptr no Visual C++).

Se o manipulador reconhece o nome do assembly, ele pode carregar e retornar um assembly que satisfaça a solicitação. A lista a seguir descreve alguns cenários de exemplo.

  • Se o manipulador conhece o local de uma versão do assembly, ele pode carregar o assembly usando o Assembly.LoadFrom ou Assembly.LoadFile método e pode retornar o assembly carregado, se for bem sucedido.

  • Se o manipulador tem acesso a um banco de dados de assemblies armazenadas como matrizes de bytes, ele pode carregar uma matriz de bytes usando um do Assembly.Load sobrecargas do método que pode levar uma matriz de bytes.

  • O manipulador pode gerar um assembly dinâmico e retorná-lo.

Observação

O manipulador deve carregar o assembly no contexto de carga, e no contexto de carregamento ou sem contexto.Se o manipulador de carrega o assembly no contexto somente de reflexão de usando o Assembly.ReflectionOnlyLoad ou o Assembly.ReflectionOnlyLoadFrom método, a carga tentativa que disparou a AssemblyResolve Falha do evento.

É responsabilidade do manipulador de eventos para retornar um conjunto adequado. O manipulador pode analisar o nome de exibição do assembly solicitado, passando a ResolveEventArgs.Name o valor da propriedade para o AssemblyName(String) construtor. Começando com o .NET Framework versão 4, o manipulador pode usar o ResolveEventArgs.RequestingAssembly a propriedade para determinar se a solicitação atual é uma dependência de outro assembly. Essas informações podem ajudar a identificar um assembly que satisfazem a dependência.

O manipulador de eventos pode retornar uma versão diferente do assembly que a versão que foi solicitada.

Na maioria dos casos, o assembly que é retornado pelo manipulador é exibida no contexto de carregamento, independentemente do contexto em que o manipulador carrega em. Por exemplo, se o manipulador usa o Assembly.LoadFrom método para carregar um assembly para o contexto de carga, o assembly é exibida no contexto de carga quando o manipulador retorna o proprietário. No entanto, no caso a seguir o conjunto aparece sem contexto quando o manipulador devolve:

Para obter informações sobre os contextos, consulte o Assembly.LoadFrom(String) sobrecarga do método.

Várias versões do mesmo assembly podem ser carregadas no mesmo domínio de aplicativo. Essa prática não é recomendada porque pode levar a problemas de atribuição de digitar. Consulte Práticas recomendadas para o carregamento de Assembly.

O que o manipulador de eventos deve fazer

A regra principal de manipulação de AssemblyResolve evento é que você não deve tentar retornar um assembly que você não reconhece. Quando você escreve o manipulador, você deve saber quais assemblies podem fazer com que o evento a ser gerado. O manipulador deve retornar null para outros assemblies.

Observação importanteImportante

Começando com o .NET Framework 4, o AssemblyResolve evento é gerado para assemblies de satélite.Essa alteração afeta um manipulador de eventos foi escrito para uma versão anterior do.NET Framework, se o manipulador tenta resolver todas as solicitações de carregamento do assembly.Manipuladores de eventos para ignorar os assemblies não reconhecem não são afetados por essa alteração: Eles retornarem nulos e mecanismos de fallback normais são seguidos.

Ao carregar um assembly, o manipulador de eventos não deve usar qualquer um do AppDomain.Load ou Assembly.Load sobrecargas do método que podem causar a AssemblyResolve evento ser elevado recursivamente, porque isso pode causar um estouro de pilha. (Consulte a lista fornecida neste tópico). Isso acontece mesmo se você fornecer o tratamento de exceções para a solicitação de carga, porque nenhuma exceção é lançada até que todos os manipuladores de evento tem retornado. Assim, o código a seguir resulta em um estouro de pilha se MyAssembly não for encontrado:

Imports System
Imports System.Reflection

Class BadExample

    Shared Sub Main()

        Dim ad As AppDomain = AppDomain.CreateDomain("Test")
        AddHandler ad.AssemblyResolve, AddressOf MyHandler

        Try
            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)
        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 System;
using System.Reflection;

class BadExample
{
    static void Main()
    {
        AppDomain ad = AppDomain.CreateDomain("Test");
        ad.AssemblyResolve += MyHandler;

        try
        {
            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);
        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.
 */
using namespace System;
using namespace System::Reflection;

ref class Example
{
internal:
    static Assembly^ MyHandler(Object^ source, ResolveEventArgs^ e) 
    {
        Console::WriteLine("Resolving {0}", e->Name);
        return Assembly::Load(e->Name);
    }
};

void main()
{
    AppDomain^ ad = AppDomain::CreateDomain("Test");
    ad->AssemblyResolve += gcnew ResolveEventHandler(&Example::MyHandler);

    try
    {
        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.
 */

Consulte também

Outros recursos

Práticas recomendadas para o carregamento de Assembly

Usando domínios de aplicativos