Megosztás a következőn keresztül:


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 partialinternal 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 HRESULTtí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 IUnknownszá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 a in 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