ICustomMarshaler Interfész
Definíció
Fontos
Egyes információk olyan, kiadás előtti termékekre vonatkoznak, amelyek a kiadásig még jelentősen módosulhatnak. A Microsoft nem vállal kifejezett vagy törvényi garanciát az itt megjelenő információért.
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
GetInstancerendező 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. |