Freigeben über


ICustomMarshaler-Schnittstelle

 

Veröffentlicht: Oktober 2016

Stellt benutzerdefinierte Wrapper für die Behandlung von Methodenaufrufen bereit.

Namespace:   System.Runtime.InteropServices
Assembly:  mscorlib (in mscorlib.dll)

Syntax

[ComVisibleAttribute(true)]
public interface ICustomMarshaler
[ComVisibleAttribute(true)]
public interface class ICustomMarshaler
[<ComVisibleAttribute(true)>]
type ICustomMarshaler = interface end
<ComVisibleAttribute(True)>
Public Interface ICustomMarshaler

Methoden

Name Beschreibung
System_CAPS_pubmethod CleanUpManagedData(Object)

Führt die notwendigen Bereinigungsvorgänge für verwalteten Daten, wenn es nicht mehr benötigt wird.

System_CAPS_pubmethod CleanUpNativeData(IntPtr)

Führt notwendigen Bereinigungsvorgänge für nicht verwalteten Daten, wenn es nicht mehr benötigt wird.

System_CAPS_pubmethod GetNativeDataSize()

Gibt die Größe der systemeigenen Daten gemarshallt werden.

System_CAPS_pubmethod MarshalManagedToNative(Object)

Konvertiert verwaltete in nicht verwaltete Daten.

System_CAPS_pubmethod MarshalNativeToManaged(IntPtr)

Konvertiert verwaltete in nicht verwaltete Daten.

Hinweise

Ein Marshaller stellt eine Brücke zwischen der Funktionalität einer alten und neuen Schnittstelle. Benutzerdefiniertes Marshalling bietet folgende Vorteile:

  • Er ermöglicht es Clientanwendungen, die entwickelt wurden mit einer alten Schnittstelle auch mit Servern arbeiten, die eine neue Schnittstelle implementieren.

  • Es ermöglicht Clientanwendungen für die Arbeit mit neuen Schnittstellen mit Servern arbeiten, die eine alte Schnittstelle implementieren.

Wenn Sie eine Schnittstelle, die verschiedene Marshallingverhalten führt oder das Component Object Model (COM) auf andere Weise verfügbar gemachte, können Sie einen benutzerdefinierten Marshaller anstelle des Interop-Marshallers entwerfen. Verwenden Sie einen benutzerdefinierten Marshaller, können Sie den Unterschied zwischen neuen .NET Framework-Komponenten und vorhandenen COM-Komponenten minimieren.

Angenommen, Sie eine verwaltete Schnittstelle namens entwickeln INew. Wenn diese Schnittstelle für COM durch einen standard COM callable Wrapper (CCW) verfügbar gemacht wird, verfügt über die gleichen Methoden wie die verwaltete Schnittstelle und verwendet die der Interop-Marshaller Marshallregeln. Angenommen, eine bekannte COM-Schnittstelle namens IOld enthält bereits die gleiche Funktionalität wie die INew Schnittstelle. Entwerfen Sie einen benutzerdefinierten Marshaller, bieten Sie eine nicht verwaltete Implementierung von IOld die einfach die Aufrufe an die verwaltete Implementierung der delegiert die INew Schnittstelle. Der benutzerdefinierte Marshaller verhält sich daher als Brücke zwischen den verwalteten und nicht verwalteten Schnittstellen.

Hinweis

Benutzerdefinierte Marshaller werden nicht aufgerufen, wenn aus verwaltetem Code an nicht verwalteten Code auf eine auf Dispatch beschränkte Schnittstelle aufrufen.

Definieren des Marshallingtyps

Bevor Sie einen benutzerdefinierten Marshaller erstellen können, müssen Sie die verwalteten und nicht verwalteten Schnittstellen definieren, die gemarshallt werden. Diese Schnittstellen führen dieselbe Funktion häufig jedoch anders für verwaltete und nicht verwaltete Objekte bereitgestellt wurden.

Ein verwalteter Compiler erstellt eine verwaltete Schnittstelle aus Metadaten und die resultierende Schnittstelle sieht wie eine beliebige andere verwaltete Schnittstelle. Das folgende Beispiel zeigt eine typische-Schnittstelle.

public interface INew
{
    void NewMethod();
}
Public Interface INew
    Sub NewMethod()
End Interface
public interface class INew
{
    void NewMethod();
};

Sie definieren den nicht verwalteten Typ in der Interface Definition Language (IDL), und kompilieren Sie diese mit der Microsoft Interface Definition Language (MIDL)-Compiler. Sie definieren die Schnittstelle in einer Bibliothek-Anweisung und weisen Sie ihr eine Schnittstellen-ID mit dem Attribut universellen eindeutigen Bezeichners (UUID), wie das folgende Beispiel veranschaulicht.

 [uuid(9B2BAADA-0705-11D3-A0CD-00C04FA35826)]
library OldLib {
     [uuid(9B2BAADD-0705-11D3-A0CD-00C04FA35826)]
     interface IOld : IUnknown
         HRESULT OldMethod();
}

Der MIDL-Compiler erstellt mehrere Ausgabedateien. Wenn die Schnittstelle in Old.idl definiert ist, definiert die Ausgabedatei Old_i.c eine const -Variable mit der Schnittstellenbezeichner (IID) der Schnittstelle, wie im folgende Beispiel veranschaulicht.

const IID IID_IOld = {0x9B2BAADD,0x0705,0x11D3,{0xA0,0xCD,0x00,0xC0,0x4F,0xA3,0x58,0x26}};

Die Datei Old.h wird auch durch MIDL erstellt. Sie enthält eine C++-Definition der Schnittstelle, die in C++-Quellcode aufgenommen werden kann.

Implementieren der ICustomMarshaler-Schnittstelle

Der benutzerdefinierte Marshaller muss implementieren die ICustomMarshaler Schnittstelle, um die entsprechenden Wrapper für die Laufzeit bereitzustellen.

Der folgende C#-Code zeigt die Basisschnittstelle, die durch alle benutzerdefinierten Marshaller implementiert werden muss.

public interface ICustomMarshaler
{
     Object MarshalNativeToManaged( IntPtr pNativeData );
     IntPtr MarshalManagedToNative( Object ManagedObj );
     void CleanUpNativeData( IntPtr pNativeData );
     void CleanUpManagedData( Object ManagedObj );
     int GetNativeDataSize();
}
Public Interface ICustomMarshaler
     Function MarshalNativeToManaged( pNativeData As IntPtr ) As Object
     Function MarshalManagedToNative( ManagedObj As Object ) As IntPtr
     Sub CleanUpNativeData( pNativeData As IntPtr )
     Sub CleanUpManagedData( ManagedObj As Object )
     Function GetNativeDataSize() As Integer
End Interface
public interface class ICustomMarshaler
{
     Object^ MarshalNativeToManaged( IntPtr^ pNativeData );
     IntPtr^ MarshalManagedToNative( Object^ ManagedObj );
     void CleanUpNativeData( IntPtr^ pNativeData );
     void CleanUpManagedData( Object^ ManagedObj );
     int GetNativeDataSize();
};

Die ICustomMarshaler -Schnittstelle enthält Methoden, die Unterstützung der Konvertierung, Bereinigung Support und Informationen zu den Daten, die gemarshallt werden bereitstellen.

Typ des Vorgangs

ICustomMarshaler-Methode

Beschreibung

Konvertierung (von systemeigenem zu verwaltetem Code)

MarshalNativeToManaged

Marshallt einen Zeiger auf systemeigene Daten in ein verwaltetes Objekt. Diese Methode gibt einen benutzerdefinierten Runtime callable Wrapper (RCW), der nicht verwaltete Schnittstelle marshallen kann, die als Argument übergeben wird. Der Marshaller sollte eine Instanz des benutzerdefinierten RCW für diesen Typ zurückgeben.

Konvertierung (von verwaltetem zu systemeigenem Code)

MarshalManagedToNative

Marshallt ein verwaltetes Objekt in einen Zeiger auf systemeigene Daten. Diese Methode gibt einen benutzerdefinierten COM callable Wrapper (CCW), der die verwaltete Schnittstelle marshallen kann, die als Argument übergeben wird. Der Marshaller sollte eine Instanz des benutzerdefinierten CCW für diesen Typ zurückgeben.

Bereinigung (von systemeigenem Code)

CleanUpNativeData

Ermöglicht, dass der Marshaller systemeigenen Daten (die CCW) bereinigen, die von zurückgegeben wird die MarshalManagedToNative Methode.

Bereinigung (von verwaltetem Code)

CleanUpManagedData

Ermöglicht, dass der Marshaller verwalteten Daten (die RCW) bereinigen, die von zurückgegeben wird die MarshalNativeToManaged Methode.

Informationen (native Code)

GetNativeDataSize

Gibt die Größe der nicht verwalteten Daten, die gemarshallt werden.

Umwandeln

ICustomMarshaler.MarshalNativeToManaged

Marshallt einen Zeiger auf systemeigene Daten in ein verwaltetes Objekt. Diese Methode gibt einen benutzerdefinierten Runtime callable Wrapper (RCW), der nicht verwaltete Schnittstelle marshallen kann, die als Argument übergeben wird. Der Marshaller sollte eine Instanz des benutzerdefinierten RCW für diesen Typ zurückgeben.

ICustomMarshaler.MarshalManagedToNative

Marshallt ein verwaltetes Objekt in einen Zeiger auf systemeigene Daten. Diese Methode gibt einen benutzerdefinierten COM callable Wrapper (CCW), der die verwaltete Schnittstelle marshallen kann, die als Argument übergeben wird. Der Marshaller sollte eine Instanz des benutzerdefinierten CCW für diesen Typ zurückgeben.

Bereinigung

ICustomMarshaler.CleanUpNativeData

Ermöglicht, dass der Marshaller systemeigenen Daten (die CCW) bereinigen, die von zurückgegeben wird die MarshalManagedToNative Methode.

ICustomMarshaler.CleanUpManagedData

Ermöglicht, dass der Marshaller verwalteten Daten (die RCW) bereinigen, die von zurückgegeben wird die MarshalNativeToManaged Methode.

Informationen zur Datenbankgröße

ICustomMarshaler.GetNativeDataSize

Gibt die Größe der nicht verwalteten Daten, die gemarshallt werden.

Implementieren der GetInstance-Methode

Zusätzlich zur Implementierung der ICustomMarshaler -Schnittstelle, die benutzerdefinierte Marshaller implementieren müssen eine static Methode mit dem Namen GetInstance akzeptiert eine String als Parameter und einen Rückgabetyp von ICustomMarshaler. Diese static wird durch die common Language Runtime COM-Interop-Schicht zum Instanziieren einer Instanz des benutzerdefinierten Marshaller aufgerufen. Die Zeichenfolge, die an GetInstance ist ein Cookie, mit denen die Methode den zurückgegebenen benutzerdefinierten Marshaller anpassen.

static ICustomMarshaler *GetInstance(String *pstrCookie);

Anwenden des "MarshalAsAttribute"

Um einen benutzerdefinierten Marshaller verwenden möchten, wenden Sie das MarshalAsAttribute -Attribut auf den Parameter oder ein Feld, das gemarshallt werden.

Sie müssen auch übergeben der UnmanagedType.CustomMarshaler -Enumerationswert, der MarshalAsAttributeKonstruktor. Darüber hinaus geben Sie die MarshalType Feld mit einem der folgenden benannten Parameter:

  • MarshalType (erforderlich): die Assembly qualifizierten Namen des benutzerdefinierten Marshaller. Der Name sollte den Namespace und die Klasse des benutzerdefinierten Marshallers enthalten. Wenn der benutzerdefinierte Marshaller nicht in der Assembly definiert ist, in dem es verwendet wird, müssen Sie den Namen der Assembly angeben, in denen sie definiert ist.

    Hinweis

    Können Sie die MarshalTypeRef Feld anstelle der MarshalType Feld.MarshalTypeRef akzeptiert einen Typ, der leichter festzulegen ist.

  • MarshalCookie (optional): ein Cookie, das dem benutzerdefinierten Marshaller übergeben wird. Cookies können Sie zusätzliche Informationen für den Marshaller bereitstellen. Wenn der Marshaller zum Bereitstellen mehrerer Wrapper verwendet wird, wird das Cookie z. B. einen bestimmten Wrapper identifiziert. Das Cookie wird zum Übergeben der GetInstance -Methode des Marshallers.

Die MarshalAsAttribute Attribut identifiziert den benutzerdefinierten Marshaller, damit den entsprechenden Wrapper aktiviert werden kann. Interop-Dienst für die common Language Runtime überprüft das Attribut und erstellt den benutzerdefinierten Marshaller, wenn das Argument (Parameter oder Feld) gemarshallt werden muss.

Die Laufzeit ruft dann die MarshalNativeToManaged und MarshalManagedToNative Methoden für den benutzerdefinierten Marshaller den korrekten Wrapper um die Verarbeitung des Rufs aktivieren.

Verwenden einen benutzerdefinierten Marshaller

Bei der benutzerdefinierte Marshaller abgeschlossen ist, können Sie es als einen benutzerdefinierten Wrapper für einen bestimmten Typ verwenden. Das folgende Beispiel zeigt die Definition der IUserData verwaltete Schnittstelle:

interface IUserData
{
    void DoSomeStuff(INew pINew);
}
Public Interface IUserData
    Sub DoSomeStuff(pINew As INew)
End Interface
public interface class IUserData
{
    void DoSomeStuff(INew^ pINew);
};

Im folgenden Beispiel die IUserData Schnittstelle verwendet die NewOldMarshaler benutzerdefinierten Marshaller zum Aktivieren von nicht verwalteten Clientanwendungen übergeben ein IOld Schnittstelle für die DoSomeStuff Methode. Die verwaltete Beschreibung der der DoSomeStuff -Methode übernimmt eine INew Schnittstelle, wie im vorherigen Beispiel dargestellt, während der nicht verwalteten Version von DoSomeStuff nimmt ein IOld -Schnittstellenzeiger, wie im folgenden Beispiel gezeigt.

[uuid(9B2BAADA-0705-11D3-A0CD-00C04FA35826)]
library UserLib {
     [uuid(9B2BABCD-0705-11D3-A0CD-00C04FA35826)]
     interface IUserData : IUnknown
         HRESULT DoSomeStuff(IUnknown* pIOld);
}

Die Typbibliothek, die generiert wird, durch den die verwaltete Definition der Export IUserData ergibt die in diesem Beispiel nicht die Standarddefinition dargestellte nicht verwaltete Definition. Die MarshalAsAttribute -Attribut angewendet wird, die INew -Argument in die verwaltete Definition der die DoSomeStuff -Methode gibt an, dass das Argument einen benutzerdefinierten Marshaller, wie im folgenden Beispiel gezeigt verwendet.

using System.Runtime.InteropServices;
Imports System.Runtime.InteropServices
using namespace System::Runtime::InteropServices;
interface IUserData
{
    void DoSomeStuff(
        [MarshalAs(UnmanagedType.CustomMarshaler,
             MarshalType="MyCompany.NewOldMarshaler")]
        INew pINew
    );
}
Public Interface IUserData
    Sub DoSomeStuff( _
        <MarshalAs(UnmanagedType.CustomMarshaler, _
        MarshalType := "MyCompany.NewOldMarshaler")> pINew As INew)
End Interface
public interface class IUserData
{
    void DoSomeStuff(
        [MarshalAs(UnmanagedType::CustomMarshaler,
             MarshalType="MyCompany.NewOldMarshaler")]
        INew^ pINew
    );
};

In den vorherigen Beispielen wird der erste Parameter zur Verfügung gestellt, um das MarshalAsAttribute -Attribut ist der UnmanagedType.CustomMarshaler Enumerationswert UnmanagedType.CustomMarshaler.

Der zweite Parameter ist die MarshalType Feld, das die Assembly qualifizierten Namen des benutzerdefinierten Marshallers angibt. Dieser Name besteht aus dem Namespace und die Klasse des benutzerdefinierten Marshallers (MarshalType="MyCompany.NewOldMarshaler").

Versionsinformationen

.NET Framework
Verfügbar seit 1.1

Siehe auch

System.Runtime.InteropServices-Namespace
Interoperabilität

Zurück zum Anfang