Padrão de marshaling de delegados

Um delegado gerenciado é empacotado sistema autônomo uma interface COM ou sistema autônomo um ponteiro de função, com base no mecanismo de chamada:

  • Invocação de plataforma, um delegado é empacotado sistema autônomo um ponteiro de função não gerenciada por padrão.

  • Para interoperabilidade COM, um delegado é empacotado sistema autônomo uma interface COM do tipo _Delegate por padrão.The _Delegate interface é definida na biblioteca de tipos Mscorlib.tlb e contém o Delegate.DynamicInvoke método, que permite que você chame o método que referencia o delegado.

A tabela a seguir mostra as opções de marshaling para o tipo de dados delegado gerenciado.The MarshalAsAttribute atributo fornece vários UnmanagedType valores de enumeração para realizar realizar marshaling delegados.

Tipo de enumeração

Descrição do formato não gerenciado

UnmanagedType.FunctionPtr

Um ponteiro de função não gerenciada.

UnmanagedType.Interface

Uma interface do tipo _Delegate, sistema autônomo Mscorlib.tlb definidos.

Considere o seguinte código de exemplo no qual os métodos de DelegateTestInterface são exportadas para uma biblioteca de tipos COM. Observe que apenas delega marcados com o ref (or ByRef) palavra-chave são passados sistema autônomo in/out parâmetros.

using System;
using System.Runtime.InteropServices;

public interface DelegateTest {
void m1(Delegate d);
void m2([MarshalAs(UnmanagedType.Interface)] Delegate d);   
void m3([MarshalAs(UnmanagedType.Interface)] ref Delegate d);  
void m4([MarshalAs(UnmanagedType.FunctionPtr)] Delegate d); 
void m5([MarshalAs(UnmanagedType.FunctionPtr)] ref Delegate d);   
}

Representação de biblioteca de tipo

importlib("mscorlib.tlb");
interface DelegateTest : IDispatch {
[id(…)] HRESULT m1([in] _Delegate* d);
[id(…)] HRESULT m2([in] _Delegate* d);
[id(…)] HRESULT m3([in, out] _Delegate** d);
[id()] HRESULT m4([in] int d);
[id()] HRESULT m5([in, out] int *d);
   };

Referência um ponteiro de função pode ser cancelado, assim sistema autônomo referência qualquer Outros ponteiro de função não gerenciada pode ser cancelado.

Observação:

Uma referência ao ponteiro de função para um delegado gerenciado mantido por código não gerenciado não impede que o common linguagem tempo de execução do executar lixo coleção no objeto gerenciado.

Por exemplo, o código a seguir é incorreto porque a referência para o cb objeto, passado para o SetChangeHandler método, não mantém. cb Além da vida útil de funcionamento do Test método. Uma vez o cb o objeto é lixo coletado, o ponteiro de função passado para SetChangeHandler não é mais válido.

public class ExternalAPI {
   [DllImport("External.dll")]
   public static extern void SetChangeHandler(
      [MarshalAs(UnmanagedType.FunctionPtr)]ChangeDelegate d);
}
public delegate bool ChangeDelegate([MarshalAs(UnmanagedType.LPWStr) string S);
public class CallBackClass {
   public bool OnChange(string S){ return true;}
}
internal class DelegateTest {
   public static void Test() {
      CallBackClass cb = new CallBackClass();
      // Caution: The following reference on the cb object does not keep the 
      // object from being garbage collected after the Main method 
      // executes.
      ExternalAPI.SetChangeHandler(new ChangeDelegate(cb.OnChange));   
   }
}

Para compensar a coleta de lixo inesperado, o chamador deve garantir que o cb objeto é mantido vivo sistema autônomo longo sistema autônomo o ponteiro de função não gerenciada está em uso. Opcionalmente, você pode ter o código não gerenciado notificar o código gerenciado quando o ponteiro de função não é mais necessária, conforme mostrado no exemplo a seguir.

internal class DelegateTest {
   CallBackClass cb;
   // Called before ever using the callback function.
   public static void SetChangeHandler() {
      cb = new CallBackClass();
      ExternalAPI.SetChangeHandler(new ChangeDelegate(cb.OnChange));
   }
   // Called after using the callback function for the last time.
   public static void RemoveChangeHandler() {
      // The cb object can be collected now. The unmanaged code is 
      // finished with the callback function.
      cb = null;
   }
}

Consulte também

Conceitos

Blittable e tipos Blittable não

Atributos direcionais

Copiando e fixação

Outros recursos

Comportamento de marshaling padrão