Jegyzet
Az oldalhoz való hozzáférés engedélyezést igényel. Próbálhatod be jelentkezni vagy könyvtárat váltani.
Az oldalhoz való hozzáférés engedélyezést igényel. Megpróbálhatod a könyvtár váltását.
A nem felügyelt kód számára elérhető paraméterek és mezők a következő típusok egyikeként vannak begépelve System.Object :
Egy variáns, ha az objektum paraméter.
Felület, ha az objektum egy struktúramező.
Csak a COM-interop támogatja az objektumtípusok rendezését. Az alapértelmezett viselkedés az objektumok COM-variánsokra való beállítása. Ezek a szabályok csak a típusra Object vonatkoznak, és nem vonatkoznak az Object osztályból származó, erősen gépelt objektumokra.
Rendezési beállítások
Az alábbi táblázat a Object adattípus csoportosítási lehetőségeit mutatja be. Az MarshalAsAttribute attribútum számos UnmanagedType enumerálási értéket biztosít a marsall objektumok számára.
| Számbavétel típusa | A nem felügyelt formátum leírása |
|---|---|
|
UnmanagedType.Struct (a paraméterek alapértelmezett beállítása) |
COM-stílusú változat. |
| UnmanagedType.Interface | Egy IDispatch interfész, ha lehetséges; ellenkező esetben egy IUnknown interfész. |
|
UnmanagedType.IUnknown (a mezők alapértelmezett beállítása) |
Egy IUnknown felület. |
| UnmanagedType.IDispatch | Egy IDispatch felület. |
Az alábbi példa a felügyelt felület definícióját mutatja be a következőhöz MarshalObject: .
Interface MarshalObject
Sub SetVariant(o As Object)
Sub SetVariantRef(ByRef o As Object)
Function GetVariant() As Object
Sub SetIDispatch( <MarshalAs(UnmanagedType.IDispatch)> o As Object)
Sub SetIDispatchRef(ByRef <MarshalAs(UnmanagedType.IDispatch)> o _
As Object)
Function GetIDispatch() As <MarshalAs(UnmanagedType.IDispatch)> Object
Sub SetIUnknown( <MarshalAs(UnmanagedType.IUnknown)> o As Object)
Sub SetIUnknownRef(ByRef <MarshalAs(UnmanagedType.IUnknown)> o _
As Object)
Function GetIUnknown() As <MarshalAs(UnmanagedType.IUnknown)> Object
End Interface
interface MarshalObject {
void SetVariant(Object o);
void SetVariantRef(ref Object o);
Object GetVariant();
void SetIDispatch ([MarshalAs(UnmanagedType.IDispatch)]Object o);
void SetIDispatchRef([MarshalAs(UnmanagedType.IDispatch)]ref Object o);
[MarshalAs(UnmanagedType.IDispatch)] Object GetIDispatch();
void SetIUnknown ([MarshalAs(UnmanagedType.IUnknown)]Object o);
void SetIUnknownRef([MarshalAs(UnmanagedType.IUnknown)]ref Object o);
[MarshalAs(UnmanagedType.IUnknown)] Object GetIUnknown();
}
Az alábbi kód egy típustárba exportálja a MarshalObject felületet.
interface MarshalObject {
HRESULT SetVariant([in] VARIANT o);
HRESULT SetVariantRef([in,out] VARIANT *o);
HRESULT GetVariant([out,retval] VARIANT *o)
HRESULT SetIDispatch([in] IDispatch *o);
HRESULT SetIDispatchRef([in,out] IDispatch **o);
HRESULT GetIDispatch([out,retval] IDispatch **o)
HRESULT SetIUnknown([in] IUnknown *o);
HRESULT SetIUnknownRef([in,out] IUnknown **o);
HRESULT GetIUnknown([out,retval] IUnknown **o)
}
Feljegyzés
Az interop marshaller automatikusan felszabadít minden lefoglalt objektumot a változaton belül a hívás után.
Az alábbi példa egy formázott értéktípust mutat be.
Public Structure ObjectHolder
Dim o1 As Object
<MarshalAs(UnmanagedType.IDispatch)> Public o2 As Object
End Structure
public struct ObjectHolder {
Object o1;
[MarshalAs(UnmanagedType.IDispatch)]public Object o2;
}
A következő kód exportálja a formázott típust egy típustárba.
struct ObjectHolder {
VARIANT o1;
IDispatch *o2;
}
Objektum és felület rendezése
Ha egy objektumot a COM-nak felületként tesznek ki, akkor ez a felület lesz a felügyelt típus Object osztályfelülete (_Object felület). Ez a felület IDispatch (UnmanagedType) vagy IUnknown (UnmanagedType.IUnknown) típusként van megadva az eredményül kapott típustárban. A COM-ügyfelek dinamikusan meghívhatják a felügyelt osztály tagjait vagy a származtatott osztályok által implementált tagokat az _Object interfészen keresztül. Az ügyfél bármely más, a felügyelt típus által explicit módon implementált felületet is meghívhat QueryInterface .
Objektum rendezése Variant-ra
Ha egy objektumot egy változathoz rendeznek, a belső változattípus futásidőben lesz meghatározva a következő szabályok alapján:
Ha az objektumhivatkozás null (a Visual Basicben semmi), az objektum egy VT_EMPTY típusú változatra lesz rendezve.
Ha az objektum az alábbi táblázatban felsorolt bármilyen típusú példány, az eredményül kapott változattípust a rendezőbe beépített és a táblázatban látható szabályok határozzák meg.
Más objektumok, amelyeknek explicit módon kell szabályozni a rendezési viselkedést, implementálhatják az interfészt IConvertible . Ebben az esetben a variáns típusát a metódusból IConvertible.GetTypeCode visszaadott típuskód határozza meg. Ellenkező esetben az objektum VT_UNKNOWN típusú változatként van rendezve.
Rendszertípusok rendezése Variant-ra
Az alábbi táblázat a felügyelt objektumtípusokat és a hozzájuk tartozó COM-változattípusokat mutatja be. Ezek a típusok csak akkor lesznek konvertálva, ha a meghívott metódus aláírása típus System.Object.
| Objektumtípus | COM-változat típusa |
|---|---|
| Null objektumhivatkozás (a Visual Basicben semmi). | VT_EMPTY |
| System.DBNull | VT_NULL |
| System.Runtime.InteropServices.ErrorWrapper | VT_ERROR |
| System.Reflection.Missing | VT_ERROR E_PARAMNOTFOUND |
| System.Runtime.InteropServices.DispatchWrapper | VT_DISPATCH |
| System.Runtime.InteropServices.UnknownWrapper | VT_UNKNOWN |
| System.Runtime.InteropServices.CurrencyWrapper | VT_CY |
| System.Boolean | VT_BOOL |
| System.SByte | VT_I1 |
| System.Byte | VT_UI1 |
| System.Int16 | VT_I2 |
| System.UInt16 | VT_UI2 |
| System.Int32 | VT_I4 |
| System.UInt32 | VT_UI4 |
| System.Int64 | VT_I8 |
| System.UInt64 | VT_UI8 |
| System.Single | VT_R4 |
| System.Double | VT_R8 |
| System.Decimal | VT_DECIMAL |
| System.DateTime | VT_DATE |
| System.String | VT_BSTR |
| System.IntPtr | VT_INT |
| System.UIntPtr | VT_UINT |
| System.Array | VT_ARRAY |
MarshalObject Az előző példában definiált felület használatával az alábbi kódpéldából megtudhatja, hogyan adhat át különböző típusú változatokat egy COM-kiszolgálónak.
Dim mo As New MarshalObject()
mo.SetVariant(Nothing) ' Marshal as variant of type VT_EMPTY.
mo.SetVariant(System.DBNull.Value) ' Marshal as variant of type VT_NULL.
mo.SetVariant(CInt(27)) ' Marshal as variant of type VT_I2.
mo.SetVariant(CLng(27)) ' Marshal as variant of type VT_I4.
mo.SetVariant(CSng(27.0)) ' Marshal as variant of type VT_R4.
mo.SetVariant(CDbl(27.0)) ' Marshal as variant of type VT_R8.
MarshalObject mo = new MarshalObject();
mo.SetVariant(null); // Marshal as variant of type VT_EMPTY.
mo.SetVariant(System.DBNull.Value); // Marshal as variant of type VT_NULL.
mo.SetVariant((int)27); // Marshal as variant of type VT_I2.
mo.SetVariant((long)27); // Marshal as variant of type VT_I4.
mo.SetVariant((single)27.0); // Marshal as variant of type VT_R4.
mo.SetVariant((double)27.0); // Marshal as variant of type VT_R8.
Azok a COM-típusok, amelyek nem rendelkeznek megfelelő felügyelt típusokkal, burkolóosztályokkal, például ErrorWrapper, DispatchWrapper, UnknownWrapperés CurrencyWrapper. Az alábbi példakód bemutatja, hogyan használhatja ezeket a burkolókat különböző típusú változatok com-kiszolgálónak való átadására.
Imports System.Runtime.InteropServices
' Pass inew as a variant of type VT_UNKNOWN interface.
mo.SetVariant(New UnknownWrapper(inew))
' Pass inew as a variant of type VT_DISPATCH interface.
mo.SetVariant(New DispatchWrapper(inew))
' Pass a value as a variant of type VT_ERROR interface.
mo.SetVariant(New ErrorWrapper(&H80054002))
' Pass a value as a variant of type VT_CURRENCY interface.
mo.SetVariant(New CurrencyWrapper(New Decimal(5.25)))
using System.Runtime.InteropServices;
// Pass inew as a variant of type VT_UNKNOWN interface.
mo.SetVariant(new UnknownWrapper(inew));
// Pass inew as a variant of type VT_DISPATCH interface.
mo.SetVariant(new DispatchWrapper(inew));
// Pass a value as a variant of type VT_ERROR interface.
mo.SetVariant(new ErrorWrapper(0x80054002));
// Pass a value as a variant of type VT_CURRENCY interface.
mo.SetVariant(new CurrencyWrapper(new Decimal(5.25)));
A burkolóosztályok a System.Runtime.InteropServices névtérben vannak definiálva.
Az IConvertible interfész a Variant-hoz való rendezése
Az előző szakaszban felsoroltaktól eltérő típusok a felület implementálásával szabályozhatják a IConvertible rendezés módját. Ha az objektum megvalósítja az IConvertible interfészt, a COM-változat típusát futásidőben határozza meg a TypeCode metódusból IConvertible.GetTypeCode visszaadott számbavétel értéke.
Az alábbi táblázat az enumerálás lehetséges értékeit TypeCode és az egyes értékekhez tartozó COM-variánstípust mutatja be.
| TypeCode | COM-változat típusa |
|---|---|
| TypeCode.Empty | VT_EMPTY |
| TypeCode.Object | VT_UNKNOWN |
| TypeCode.DBNull | VT_NULL |
| TypeCode.Boolean | VT_BOOL |
| TypeCode.Char | VT_UI2 |
| TypeCode.Sbyte | VT_I1 |
| TypeCode.Byte | VT_UI1 |
| TypeCode.Int16 | VT_I2 |
| TypeCode.UInt16 | VT_UI2 |
| TypeCode.Int32 | VT_I4 |
| TypeCode.UInt32 | VT_UI4 |
| TypeCode.Int64 | VT_I8 |
| TypeCode.UInt64 | VT_UI8 |
| TypeCode.Single | VT_R4 |
| TypeCode.Double | VT_R8 |
| TypeCode.Decimális | VT_DECIMAL |
| TypeCode.DateTime | VT_DATE |
| TypeCode.String | VT_BSTR |
| Nem támogatott. | VT_INT |
| Nem támogatott. | VT_UINT |
| Nem támogatott. | VT_ARRAY |
| Nem támogatott. | VT_RECORD |
| Nem támogatott. | VT_CY |
| Nem támogatott. | VT_VARIANT |
A COM-variáns értékét a IConvertible.ToType felület meghívásával határozzuk meg, ahol To a Típus az IConvertible.GetTypeCode-ból visszaadott típusnak megfelelő konverziós rutin. Például az IConvertible.GetTypeCode-ból typeCode.Double értéket visszaadó objektum a VT_R8 típusú COM-változatként van rendezve. A variáns értékét, amely a COM-változat dblVal mezőjében van tárolva, a IConvertible interfészre történő konvertálással és a ToDouble metódus meghívásával kaphatja meg.
Variant objektumba rendezése
Amikor egy variánst objektumhoz rendez, a rendezővariáns típusa és néha értéke határozza meg a létrehozott objektum típusát. Az alábbi táblázat azonosítja az egyes változattípusokat és a megfelelő objektumtípusokat, amelyeket az m marshallerreates ad át a COM-ból a .NET-keretrendszer.
| COM-változat típusa | Objektumtípus |
|---|---|
| VT_EMPTY | Null objektumhivatkozás (a Visual Basicben semmi). |
| VT_NULL | System.DBNull |
| VT_DISPATCH | System.__ComObject vagy null, ha (pdispVal == null) |
| VT_UNKNOWN | System.__ComObject vagy null ha (punkVal == null) |
| VT_ERROR | System.UInt32 |
| VT_BOOL | System.Boolean |
| VT_I1 | System.SByte |
| VT_UI1 | System.Byte |
| VT_I2 | System.Int16 |
| VT_UI2 | System.UInt16 |
| VT_I4 | System.Int32 |
| VT_UI4 | System.UInt32 |
| VT_I8 | System.Int64 |
| VT_UI8 | System.UInt64 |
| VT_R4 | System.Single |
| VT_R8 | System.Double |
| VT_DECIMAL | System.Decimal |
| VT_DATE | System.DateTime |
| VT_BSTR | System.String |
| VT_INT | System.Int32 |
| VT_UINT | System.UInt32 |
| | VT_ARRAY VT_* | System.Array |
| VT_CY | System.Decimal |
| VT_RECORD | Megfelelő dobozos értéktípus. |
| VT_VARIANT | Nem támogatott. |
Előfordulhat, hogy a COM-ból a felügyelt kódba, majd a COM-ba visszakerülő változattípusok a hívás időtartama alatt nem őrzik meg ugyanazt a változattípust. Gondolja át, mi történik, ha a COM-ból a .NET-keretrendszerbe továbbít egy típusvariánst VT_DISPATCH . A rendezés során a rendszer átalakítja a variánst .System.Object Ha a Object ezt követően visszakerül a COM-hoz, akkor egy VT_UNKNOWN típusú változatra lesz átültetve. Nincs garancia arra, hogy az objektum felügyelt kódból COM-ba való beállításakor előállított változat ugyanaz a típus lesz, mint az objektum előállításához eredetileg használt változat.
ByRef-változatok rendezése
Bár maguk a változatok átadhatók érték vagy hivatkozás alapján, a VT_BYREF jelölő bármely változattípussal is használható annak jelzésére, hogy a változat tartalmát hivatkozással, nem pedig érték alapján adja át. A változatok referencia alapján történő rendezése és a jelölőkészlettel való VT_BYREF rendezés közötti különbség zavaró lehet. Az alábbi ábra tisztázza a különbségeket:
Érték és hivatkozás szerint átadott variánsok
Objektumok és változatok érték szerinti rendezési viselkedése
Ha objektumokat ad át a felügyelt kódból a COM-nak, az objektum tartalma a rendező által létrehozott új változatba lesz másolva a Marshalling Object to Variant parancsban meghatározott szabályok használatával. A nem felügyelt oldalon végrehajtott módosításokat a rendszer nem propagálja vissza az eredeti objektumra a hívásból való visszatéréskor.
Ha a com-ról felügyelt kódra továbbítja a variánsokat, a rendszer egy újonnan létrehozott objektumba másolja a változat tartalmát a Marshalling Variant objektumba definiált szabályokkal. A felügyelt oldalon az objektum módosításai nem lesznek visszaterjesztve az eredeti változatra a hívásból való visszatéréskor.
Objektumok és változatok beállításának alapértelmezett viselkedése hivatkozás alapján
Ha a módosításokat vissza szeretné propagálja a hívónak, a paramétereket hivatkozással kell átadni. Használhatja például a kulcsszót a ref C# (vagy ByRef a Visual Basic felügyelt kódban) a paraméterek hivatkozással történő átadásához. A COM-ban a referenciaparaméterek egy mutató, például egy *változat használatával lesznek átadva.
Amikor egy objektumot hivatkozással ad át a COM-nak, a rendező létrehoz egy új változatot, és a hívás előtt átmásolja az objektumhivatkozás tartalmát a változatba. A variáns a nem felügyelt függvénynek lesz átadva, ahol a felhasználó szabadon módosíthatja a változat tartalmát. A hívásból való visszatéréskor a nem felügyelt oldalon végrehajtott módosításokat a rendszer visszaterjeszti az eredeti objektumra. Ha a változat típusa eltér a hívásnak átadott változat típusától, a rendszer a módosításokat egy másik típusú objektumra propagálja. Vagyis a hívásba átadott objektum típusa eltérhet a hívásból visszaadott objektum típusától.
Ha egy változatot referencia alapján ad át a felügyelt kódnak, a rendező létrehoz egy új objektumot, és a hívás előtt átmásolja a változat tartalmát az objektumba. Az objektumra mutató hivatkozást a rendszer átadja a felügyelt függvénynek, ahol a felhasználó szabadon módosíthatja az objektumot. A hívásból való visszatéréskor a hivatkozott objektumon végrehajtott módosítások az eredeti változatra lesznek propagálva. Ha az objektum típusa eltér a hívásnak átadott objektum típusától, az eredeti változat típusa megváltozik, és az érték visszakerül a változatba. A hívásba átadott változat típusa is eltérhet a hívásból visszaadott változat típusától.
A VT_BYREF jelzőkészlettel rendelkező változatok beállításának alapértelmezett viselkedése
A felügyelt kódnak érték szerint átadott variánsok
VT_BYREFjelölője azt jelezheti, hogy a változat egy érték helyett egy hivatkozást tartalmaz. Ebben az esetben a variáns továbbra is egy objektumhoz van rendezve, mert a variánst érték adja át. A rendező automatikusan elhalasztja a változat tartalmát, és egy újonnan létrehozott objektumba másolja a hívást. Az objektum ezután bekerül a felügyelt függvénybe; azonban a hívásból való visszatéréskor az objektum nem lesz újra propagálva az eredeti változatba. A felügyelt objektum módosításai elvesznek.Figyelemfelhívás
Az érték által átadott változatok értékét nem lehet módosítani, még akkor sem, ha a variáns rendelkezik a
VT_BYREFjelölőkészlettel.A felügyelt kódnak hivatkozással átadott változatok
VT_BYREFjelölője azt is jelezheti, hogy a változat egy másik hivatkozást tartalmaz. Ha igen, akkor a variáns egyrefobjektumhoz lesz rendezve, mert a variánst hivatkozással továbbítja a függvény. A rendező automatikusan elhalasztja a változat tartalmát, és egy újonnan létrehozott objektumba másolja a hívást. A hívásból való visszatéréskor az objektum értékét a rendszer csak akkor propagálja vissza az eredeti változatban lévő hivatkozásra, ha az objektum típusa megegyezik az átadott objektum típusával. Ez azt jelenti, hogy a propagálás nem változtatja meg a jelölőkészlettel rendelkezőVT_BYREFváltozat típusát. Ha az objektum típusa módosul a hívás során, InvalidCastException a hívásból való visszatéréskor történik.
Az alábbi táblázat összefoglalja a variánsok és objektumok propagálási szabályait.
| Forrás | Művelet | A módosítások újraterjesztése |
|---|---|---|
| Variantv | Objektumo | Soha |
| Objektumo | Variantv | Soha |
| Változat*Pv | Ref Objecto | Mindig |
| Ref objektumo | Változat*Pv | Mindig |
| Vváltozat(VT_BYREF|VT_*) | Objektumo | Soha |
| Variantv(VT_BYREF|VT_) | Ref Objecto | Csak akkor, ha a típus nem változott. |