Forrásgenerálás a ComWrappershez
A .NET 8 egy forrásgenerátort vezet be, amely létrehozza a ComWrappers API implementációját. A generátor felismeri a GeneratedComInterfaceAttribute.
A .NET-futtatókörnyezet beépített (nem forrás által generált), Windows-only, COM interop rendszer létrehoz egy IL-csonkot – a JIT-ed il utasítások streamjét – futásidőben, hogy megkönnyítse a felügyelt kódról a COM-ra való áttérést, és fordítva. Mivel ez az IL-csonk futásidőben jön létre, nem kompatibilis a NativeAOT és az IL vágással. A csonkok futásidőben történő létrehozása a rendezési problémák diagnosztizálását is megnehezítheti.
A beépített interop olyan attribútumokat használ, mint a ComImport
vagy DllImport
, amelyek futásidőben kódgenerálásra támaszkodnak. Az alábbi kód erre mutat példát:
[ComImport]
interface IFoo
{
void Method(int i);
}
[DllImport("MyComObjectProvider.dll")]
static nint GetPointerToComInterface();
[DllImport("MyComObjectProvider.dll")]
static void GivePointerToComInterface(nint comObject);
// Use the system to create a Runtime Callable Wrapper to use in managed code
nint ptr = GetPointerToComInterface();
IFoo foo = (IFoo)Marshal.GetObjectForIUnknown(ptr);
foo.Method(0);
...
// Use the system to create a COM Callable Wrapper to pass to unmanaged code
IFoo foo = GetManagedIFoo();
nint ptr = Marshal.GetIUnknownForObject(foo);
GivePointerToComInterface(ptr);
Az ComWrappers
API lehetővé teszi a COM használatát C#-ban a beépített COM-rendszer használata nélkül, de jelentős mennyiségű sablont és kézzel írt nem biztonságos kódot igényel. A COM felületgenerátor automatizálja ezt a folyamatot, és olyan egyszerűvé teszi ComWrappers
, mint a beépített COM, de vágható és AOT-barát módon biztosítja.
Alapszintű használat
A COM-felületgenerátor használatához adja hozzá a GeneratedComInterfaceAttribute COM-ból importálni vagy a COM-nak elérhetővé tenni kívánt felületdefinícióhoz azokat és GuidAttribute attribútumokat. A típust meg kell jelölni partial
, és rendelkeznie internal
kell a létrehozott kód láthatóságával vagy public
láthatóságával ahhoz, hogy hozzáférhessen a kódhoz.
[GeneratedComInterface]
[Guid("3faca0d2-e7f1-4e9c-82a6-404fd6e0aab8")]
internal partial interface IFoo
{
void Method(int i);
}
Ezután a COM felületét implementáló osztályt úgy teheti elérhetővé, hogy hozzáadja a GeneratedComClassAttribute implementáló osztályhoz. Ennek az osztálynak partial
internal
vagy vagy public
.
[GeneratedComClass]
internal partial class Foo : IFoo
{
public void Method(int i)
{
// Do things
}
}
Fordításkor a generátor létrehozza a ComWrappers API implementációját, és használhatja a StrategyBasedComWrappers típust vagy egy egyéni származtatott típust a COM-felület felhasználásához vagy elérhetővé megvalósításához.
[LibraryImport("MyComObjectProvider.dll")]
static nint GetPointerToComInterface();
[LibraryImport("MyComObjectProvider.dll")]
static void GivePointerToComInterface(nint comObject);
// Use the ComWrappers API to create a Runtime Callable Wrapper to use in managed code
ComWrappers cw = new StrategyBasedComWrappers();
nint ptr = GetPointerToComInterface();
IFoo foo = (IFoo)cw.GetOrCreateObjectForComInterface(ptr);
foo.Method(0);
...
// Use the system to create a COM Callable Wrapper to pass to unmanaged code
ComWrappers cw = new StrategyBasedComWrappers();
Foo foo = new();
nint ptr = cw.GetOrCreateComInterfaceForObject(foo);
GivePointerToComInterface(ptr);
Rendezés testreszabása
A COM-felületgenerátor tiszteletben tartja az MarshalUsingAttribute attribútumot és az attribútum egyes használati módjait a MarshalAsAttribute paraméterek testreszabásához. További információkért tekintse meg, hogyan szabhatja testre a forrás által létrehozott rendezést az attribútummal, és hogyan szabhatja testre a MarshalUsing
paraméter-rendezést az MarshalAs
attribútummal. A GeneratedComInterfaceAttribute.StringMarshalling tulajdonságok az GeneratedComInterfaceAttribute.StringMarshallingCustomType interfész összes paraméterére vonatkoznak, és visszaadják a típustípusokat string
, ha nem rendelkeznek más rendezési attribútumokkal.
Implicit HRESULTs és PreserveSig
A C# COM-metódusai más aláírással rendelkeznek, mint a natív metódusok. A standard COM visszatérési HRESULT
típusa 4 bájt egész szám, amely hiba- és sikerállapotokat jelöl. Ez a HRESULT
visszatérési érték alapértelmezés szerint rejtett a C#-aláírásban, és hibaérték visszaadásakor kivételré alakul. A natív COM-aláírás utolsó "out" paramétere opcionálisan átalakítható a C#-aláírás visszatérési értékévé.
Az alábbi kódrészletek például c# metódusaláírásokat és a generátor által kikövetkeztetett natív aláírást jelenítik meg.
void Method1(int i);
int Method2(float i);
HRESULT Method1(int i);
HRESULT Method2(float i, _Out_ int* returnValue);
Ha szeretné kezelni magát HRESULT
, használhatja a PreserveSigAttribute módszert, hogy jelezze a generátor nem szabad ezt az átalakítást. Az alábbi kódrészletek bemutatják, hogy a generátor milyen natív aláírást vár el az alkalmazáskor [PreserveSig]
. A COM-metódusokat vissza kell adni HRESULT
, így bármely metódus PreserveSig
visszatérési értéke legyen int
.
[PreserveSig]
int Method1(int i, out int j);
[PreserveSig]
int Method2(float i);
HRESULT Method1(int i, int* j);
HRESULT Method2(float i);
További információ: Implicit metódus aláírás fordítása a .NET interopban
Inkompatibilitások és különbségek a beépített COM-ban
IUnknown
Csak
Az egyetlen támogatott felületi alap a IUnknown
. Azok a InterfaceTypeAttribute felületek, amelyek értéke nem InterfaceIsIUnknown a forrás által létrehozott COM-ban támogatott, nem támogatottak. Minden olyan illesztő, amely nem rendelkezik a InterfaceTypeAttribute
következőből IUnknown
származtatható: . Ez eltér a beépített COM-tól, ahol az alapértelmezett érték .InterfaceIsDual
Alapértelmezett beállítások és támogatás beállítása
A forrás által létrehozott COM különböző alapértelmezett rendezési viselkedésekkel rendelkezik a beépített COM-tól.
A beépített COM rendszerben minden típus implicit attribútummal rendelkezik
[In]
, kivéve a tömböket, amelyek implicit[In, Out]
attribútumokkal rendelkeznek. A forrás által létrehozott COM-ban minden típus, beleértve a tömböket is, szemantikával rendelkezik[In]
.[In]
és[Out]
az attribútumok csak tömbökben engedélyezettek.[In, Out]
Ha[Out]
más típusok esetében szükség van viselkedésre, használja ain
paramétermódosítókatout
.
Származtatott interfészek
A beépített COM-rendszerben, ha más COM-felületekből származó felületekkel rendelkezik, minden alapmetódushoz deklarálnia kell egy árnyékolási módszert a new
kulcsszóval rendelkező alapfelületeken. További információ: COM-felület öröklése és .NET.
[ComImport]
[Guid("3faca0d2-e7f1-4e9c-82a6-404fd6e0aab8")]
interface IBase
{
void Method1(int i);
void Method2(float i);
}
[ComImport]
[Guid("3faca0d2-e7f1-4e9c-82a6-404fd6e0aab8")]
interface IDerived : IBase
{
new void Method1(int i);
new void Method2(float f);
void Method3(long l);
void Method4(double d);
}
A COM-felületgenerátor nem számít az alapmódszerek árnyékolására. Ha egy másiktól öröklő metódust szeretne létrehozni, egyszerűen jelölje meg az alapfelületet C# alapfelületként, és adja hozzá a származtatott felület metódusait. További információkért tekintse meg a tervezési dokumentumot.
[GeneratedComInterface]
[Guid("3faca0d2-e7f1-4e9c-82a6-404fd6e0aab8")]
interface IBase
{
void Method1(int i);
void Method2(float i);
}
[GeneratedComInterface]
[Guid("3faca0d2-e7f1-4e9c-82a6-404fd6e0aab8")]
interface IDerived : IBase
{
void Method3(long l);
void Method4(double d);
}
Vegye figyelembe, hogy az GeneratedComInterface
attribútummal rendelkező felület csak egy olyan alapfelülettől örökölhető, amely rendelkezik az GeneratedComInterface
attribútummal.
Marshal API-k
Egyes API-k Marshal nem kompatibilisek a forrás által létrehozott COM-val. Cserélje le ezeket a metódusokat a megvalósításhoz ComWrappers
kapcsolódó metódusokra.
Lásd még
Visszajelzés
https://aka.ms/ContentUserFeedback.
Hamarosan elérhető: 2024-ben fokozatosan kivezetjük a GitHub-problémákat a tartalom visszajelzési mechanizmusaként, és lecseréljük egy új visszajelzési rendszerre. További információ:Visszajelzés küldése és megtekintése a következőhöz: