ICustomMarshaler Interfész

Definíció

Egyéni burkolókat biztosít a metódushívások kezeléséhez.

public interface class ICustomMarshaler
public interface ICustomMarshaler
[System.Runtime.InteropServices.ComVisible(true)]
public interface ICustomMarshaler
type ICustomMarshaler = interface
[<System.Runtime.InteropServices.ComVisible(true)>]
type ICustomMarshaler = interface
Public Interface ICustomMarshaler
Származtatott
Attribútumok

Megjegyzések

Az ICustomMarshaler interfész egyéni burkolókat biztosít a metódushívások kezeléséhez.

A marshaller hidat biztosít a régi és az új felületek funkciói között. Az egyéni marsallálás a következő előnyöket nyújtja:

  • Lehetővé teszi, hogy a régi felülettel működő ügyfélalkalmazások új felületet implementáló kiszolgálókkal is működjenek.
  • Lehetővé teszi, hogy az ügyfélalkalmazások új felülettel működjenek együtt egy régi felületet implementáló kiszolgálókkal.

Ha olyan kezelőfelülettel rendelkezik, amely eltérő marsallálási viselkedést vezet be, vagy más módon jelenik meg a komponensobjektum-modell (COM) számára, az interop marshaller használata helyett egyéni rendezőt is tervezhet. Egyéni rendező használatával minimalizálhatja az új .NET összetevők és a meglévő COM-összetevők közötti különbséget.

Tegyük fel például, hogy egy INew nevű felügyelt felületet fejleszt. Ha ez a felület egy szabványos COM hívható burkolón (CCW) keresztül érhető el a COM számára, ugyanazokkal a metódusokkal rendelkezik, mint a felügyelt felület, és az interop marshallerbe beépített marshaling szabályokat használja. Tegyük fel, hogy egy jól ismert COM-felület, mint a IOld, már ugyanazt a funkciót biztosítja, mint a INew felület. Egyéni rendező tervezésével olyan nem felügyelt implementációt IOld biztosíthat, amely egyszerűen delegálja a hívásokat a INew felület felügyelt implementációjára. Ezért az egyéni marshaling hídként működik a felügyelt és nem felügyelt felületek között.

Note

Az egyéni rendezők nem lesznek meghívva, amikor felügyelt kódból nem felügyelt kódra hívnak meg egy csak küldési felületen.

Marshaling típusának meghatározása

Mielőtt létrehozná az egyéni marshallert, meg kell határoznia a felügyelt és nem felügyelt felületeket, amelyek marshalling során lesznek használva. Ezek az interfészek általában ugyanazt a funkciót hajtják végre, de másként vannak kitéve a felügyelt és nem felügyelt objektumoknak.

A felügyelt fordítók a metaadatokból létrehoznak egy felügyelt felületet, és az eredményként kapott felület úgy néz ki, mint bármely más felügyelt felület. Az alábbi példa egy tipikus felületet mutat be.

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

A nem felügyelt típust az Interfészdefiníciós nyelvben (IDL) definiálhatja, és lefordíthatja a Microsoft Interface Definition Language (MIDL) fordítóval. Egy kódtár-utasításban definiálja a felületet, és hozzárendel egy interfészazonosítót az univerzális egyedi azonosító (UUID) attribútummal, ahogyan az az alábbi példában is látható.

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

A MIDL-fordító több kimeneti fájlt is létrehoz. Ha az interfész az Old.idl fájlban van definiálva, a Old_i.c kimeneti fájl definiál egy const változót az interfész interfészazonosítójával (IID) az alábbi példában látható módon.

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

Az Old.h fájlt a MIDL is előállítja. A C++ forráskódban is szerepelhet a felület C++ definíciója.

Az ICustomMarshaler felület implementálása

Az egyéni csomagolónak implementálnia kell az ICustomMarshaler interfészt, hogy a megfelelő burkolóelemeket biztosítsa a futtatókörnyezetnek.

Az alábbi C#-kód megjeleníti az alap interfészt, amelyet minden egyéni marshállernek implementálnia kell.

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

Az ICustomMarshaler interfész olyan metódusokat tartalmaz, amelyek konverziós támogatást, törlési támogatást és a marsallandó adatokra vonatkozó információkat biztosítanak.

Művelet típusa ICustomMarshaler metódus Description
Átalakítás (natív kódról felügyelt kódra) MarshalNativeToManaged Egy natív adatokra mutató mutatót helyez egy felügyelt objektumba. Ez a metódus egy egyéni futásidejű hívható burkolót (RCW) ad vissza, amely az argumentumként átadott nem felügyelt felületet továbbítja. Az átalakítónak az egyéni RCW egy példányát kell visszaadnia az adott típushoz.
Átalakítás (felügyeltről natív kódra) MarshalManagedToNative Egy felügyelt objektumot natív adatokra mutató mutatóvá alakít. Ez a metódus egy egyéni COM-hívható burkolót (CCW) ad vissza, amely az argumentumként átadott felügyelt felületet továbbítja. A kialakítónak a testre szabott CCW egy példányát kell visszaadnia ehhez a típushoz.
Törlés (natív kód) CleanUpNativeData Lehetővé teszi a marshaller számára, hogy megtisztítsa a metódus által visszaadott natív adatokat (a CCW-t) MarshalManagedToNative .
Törlés (felügyelt kód) CleanUpManagedData Lehetővé teszi a rendező számára a metódus által visszaadott felügyelt adatok (RCW) törlését MarshalNativeToManaged .
Információk (a natív kódról) GetNativeDataSize A kihelyezésre kerülő nem felügyelt adatok méretét adja vissza.

Conversion

ICustomMarshaler.MarshalNativeToManaged

Egy natív adatokra mutató mutatót helyez egy felügyelt objektumba. Ez a metódus egy egyéni futásidejű hívható burkolót (RCW) ad vissza, amely az argumentumként átadott nem felügyelt felületet továbbítja. Az átalakítónak az egyéni RCW egy példányát kell visszaadnia az adott típushoz.

ICustomMarshaler.MarshalManagedToNative

Egy felügyelt objektumot natív adatokra mutató mutatóvá alakít. Ez a metódus egy egyéni COM-hívható burkolót (CCW) ad vissza, amely az argumentumként átadott felügyelt felületet továbbítja. A kialakítónak a testre szabott CCW egy példányát kell visszaadnia ehhez a típushoz.

Takarítás

ICustomMarshaler.CleanUpNativeData

Lehetővé teszi a marshaller számára, hogy megtisztítsa a metódus által visszaadott natív adatokat (a CCW-t) MarshalManagedToNative .

ICustomMarshaler.CleanUpManagedData

Lehetővé teszi a rendező számára a metódus által visszaadott felügyelt adatok (RCW) törlését MarshalNativeToManaged .

Méretadatok

ICustomMarshaler.GetNativeDataSize

A kihelyezésre kerülő nem felügyelt adatok méretét adja vissza.

Note

Ha egy egyéni marshaller meghívja azokat a metódusokat, amelyek a legutóbbi P/Invoke hibát állítják be natívról felügyeltre történő marshaling vagy tisztítás során, a visszaadott Marshal.GetLastWin32Error() és Marshal.GetLastPInvokeError() érték a marshaling vagy a cleanup hívások hívását fogja tükrözni. Ez ahhoz vezethet, hogy a DllImportAttribute.SetLastError értékre állított true egyéni marshaller-ek használatakor a hibák észrevétlenek maradnak a P/Invokes során. Az utolsó P/Invoke hiba megőrzéséhez használja az Marshal.GetLastPInvokeError() implementációban lévő Marshal.SetLastPInvokeError(Int32) metódusokat és ICustomMarshaler metódusokat.

A GetInstance metódus implementálása

Az ICustomMarshaler interfész implementálása mellett az egyéni marshallereknek egy static metódust is implementálniuk kell, amelynek neve GetInstance, egy String paraméterként fogad el, és ICustomMarshaler típusú értéket ad vissza. A közös nyelvi futtatókörnyezet COM interop rétege hívja meg ezt a static metódust az egyéni marschall példányának példányosítására. Az GetInstance-nek átadott sztring egy cookie, amellyel a metódus testre szabhatja a visszaadott egyéni csatolót. Az alábbi példa egy minimális, de teljes ICustomMarshaler implementációt mutat be.

public class NewOldMarshaler : ICustomMarshaler
{
    public static ICustomMarshaler GetInstance(string pstrCookie)
        => new NewOldMarshaler();

    public Object MarshalNativeToManaged(IntPtr pNativeData) => throw new NotImplementedException();
    public IntPtr MarshalManagedToNative(Object ManagedObj) => throw new NotImplementedException();
    public void CleanUpNativeData(IntPtr pNativeData) => throw new NotImplementedException();
    public void CleanUpManagedData(Object ManagedObj) => throw new NotImplementedException();
    public int GetNativeDataSize() => throw new NotImplementedException();
}

MarshalAsAttribute alkalmazása

Egyedi marshaller használatához alkalmaznia kell az MarshalAsAttribute attribútumot arra a paraméterre vagy mezőre, amelyet marshalol.

Az enumerálási UnmanagedType.CustomMarshaler értéket is át kell adnia a MarshalAsAttribute konstruktornak. Emellett meg kell adnia a MarshalType mezőt a következő elnevezett paraméterek egyikével:

  • MarshalType (kötelező): Az egyéni marshaller összeállítás-minősített neve. A névnek tartalmaznia kell az egyedi marshaler névterét és osztályát. Ha az egyéni marshal nincs definiálva abban az assemblyben, amelyben használva van, meg kell adnia annak az assemblynek a nevét, amelyben definiálva van.

    Note

    A MarshalTypeRef mezőt használhatja a MarshalType mező helyett. MarshalTypeRef egy könnyebben megadható típust vesz fel.

  • MarshalCookie (nem kötelező): Az egyéni rendezőnek átadott cookie. A cookie használatával további információkat adhat meg a rendezőnek. Ha például ugyanazt a rendezőt használja több burkoló megadásához, a cookie azonosít egy adott burkolót. A cookie-t átadjuk a GetInstance rendező metódusának.

Az MarshalAsAttribute attribútum azonosítja az egyéni marshal-t, hogy aktiválhassa a megfelelő burkolót. A közös nyelvi futtatókörnyezet interop szolgáltatása ezután megvizsgálja az attribútumot, és létrehozza az egyéni rendezőt az argumentum (paraméter vagy mező) első marshalizációjakor.

A futtatókörnyezet ezután meghívja az egyéni megtöltő metódusok közül az MarshalNativeToManaged és MarshalManagedToNative metódusokat, hogy aktiválja a megfelelő burkolót a hívás kezeléséhez.

Egyéni marshaloló használata

Amikor az egyéni marshaller elkészült, használhatja csomagolóként egy adott típushoz. Az alábbi példa a felügyelt felület definícióját IUserData mutatja be:

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

Az alábbi példában a IUserData interfész a NewOldMarshaler egyéni rendezőt használja annak érdekében, hogy a nem felügyelt ügyfélalkalmazások egy IOld interfészt adhassanak át a DoSomeStuff metódusnak. A metódus felügyelt leírása DoSomeStuff egy INew felületet használ, ahogyan az előző példában is látható, míg a nem felügyelt verzió DoSomeStuff egy IOld interfészmutatót vesz fel, ahogyan az az alábbi példában látható.

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

A felügyelt definíció IUserData exportálásával létrehozott típustár a standard definíció helyett az ebben a példában látható nem felügyelt definíciót hozza létre. A MarshalAsAttribute metódus felügyelt definíciójában INew az DoSomeStuff argumentumra alkalmazott attribútum azt jelzi, hogy az argumentum egyéni rendezőt használ, ahogyan az az alábbi példában is látható.

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

Az előző példákban az attribútumhoz MarshalAsAttribute megadott első paraméter az UnmanagedType.CustomMarshaler enumerálási érték UnmanagedType.CustomMarshaler.

A második paraméter a MarshalType mező, amely az egyéni marshaller szerelvényrel minősített nevét adja meg. Ez a név az egyéni marshaller (MarshalType="MyCompany.NewOldMarshaler") névteréből és osztályából áll.

Metódusok

Name Description
CleanUpManagedData(Object)

Elvégzi a felügyelt adatok szükséges törlését, ha már nincs rá szükség.

CleanUpNativeData(IntPtr)

Elvégzi a nem felügyelt adatok szükséges törlését, ha már nincs rá szükség.

GetNativeDataSize()

A marsallandó natív adatok méretét adja vissza.

MarshalManagedToNative(Object)

A felügyelt adatokat nem felügyelt adatokká alakítja.

MarshalNativeToManaged(IntPtr)

A nem felügyelt adatokat felügyelt adatokká alakítja.

A következőre érvényes: