Sdílet prostřednictvím


Generování zdroje pro comWrappers

.NET 8 zavádí zdrojový generátor, který za vás vytvoří implementaci rozhraní API ComWrappers . Generátor rozpozná GeneratedComInterfaceAttribute.

Integrovaný (negenerovaný) modul runtime .NET, pouze windows, interopový systém MODELU COM generuje zástupnou proceduru IL – tok instrukcí IL, který je za běhu jit-ed– pro usnadnění přechodu ze spravovaného kódu na com a naopak. Vzhledem k tomu, že se tato procedura IL generuje za běhu, není kompatibilní s ořezáváním NativeAOT a IL. Generování zástupných procedur za běhu může také ztížit diagnostiku problémů se seřazováním.

Integrovaná interoperabilita používá atributy, jako ComImport jsou například nebo DllImport, které spoléhají na generování kódu za běhu. Následující kód ukazuje příklad:

[ComImport]
interface IFoo
{
    void Method(int i);
}

[DllImport("MyComObjectProvider")]
static nint GetPointerToComInterface(); // C definition - IUnknown* GetPointerToComInterface();

[DllImport("MyComObjectProvider")]
static void GivePointerToComInterface(nint comObject); // C definition - void GivePointerToComInterface(IUnknown* pUnk);

// 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);

Rozhraní ComWrappers API umožňuje interakci s com v jazyce C# bez použití integrovaného systému COM, ale vyžaduje značné často používané a ručně napsané nebezpečné kódy. Generátor rozhraní COM tento proces automatizuje a usnadňuje ComWrappers tak, jak je integrovaný com, ale dodává ho ořízitelným a přívětivým způsobem.

Základní použití

Pokud chcete použít generátor rozhraní MODELU COM, přidejte GeneratedComInterfaceAttribute atributy GuidAttribute do definice rozhraní, ze které chcete importovat nebo zpřístupnit modelu COM. Typ musí být označený partial a musí mít public internal viditelnost vygenerovaného kódu, aby k němu měl přístup.

[GeneratedComInterface]
[Guid("3faca0d2-e7f1-4e9c-82a6-404fd6e0aab8")]
internal partial interface IFoo
{
    void Method(int i);
}

Pak chcete-li zveřejnit třídu, která implementuje rozhraní modelu COM, přidejte GeneratedComClassAttribute do implementní třídy. Tato třída musí být partial také a buď internal nebo public.

[GeneratedComClass]
internal partial class Foo : IFoo
{
    public void Method(int i)
    {
        // Do things
    }
}

V době kompilace generátor vytvoří implementaci rozhraní COMWrappers a můžete použít StrategyBasedComWrappers typ nebo vlastní odvozený typ ke zpracování nebo zveřejnění rozhraní COM.

[LibraryImport("MyComObjectProvider")]
private static partial nint GetPointerToComInterface(); // C definition - IUnknown* GetPointerToComInterface();

[LibraryImport("MyComObjectProvider")]
private static partial void GivePointerToComInterface(nint comObject); // C definition - void GivePointerToComInterface(IUnknown* pUnk);

// 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.GetOrCreateObjectForComInstance(ptr, CreateObjectFlags.None);
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, CreateComInterfaceFlags.None);
GivePointerToComInterface(ptr);

Přizpůsobení zařazování

Generátor rozhraní MODELU COM respektuje MarshalUsingAttribute atribut a některé použití MarshalAsAttribute atributu k přizpůsobení zařazování parametrů. Další informace najdete v tématu přizpůsobení zdrojového zařazování pomocí atributu MarshalUsing a přizpůsobení zařazování parametrů pomocí atributuMarshalAs. Vlastnosti GeneratedComInterfaceAttribute.StringMarshalling platí GeneratedComInterfaceAttribute.StringMarshallingCustomType pro všechny parametry a návratové typy typu string v rozhraní, pokud nemají jiné atributy zařazování.

Implicitní hodnoty HRESULT a PreserveSig

Metody MODELU COM v jazyce C# mají jiný podpis než nativní metody. Standardní com má návratový HRESULTtyp , 4 bajtové celé číslo představující chybové a úspěšné stavy. Tato HRESULT návratová hodnota je ve výchozím nastavení v podpisu jazyka C# skrytá a při vrácení chybové hodnoty se převede na výjimku. Poslední parametr out nativního podpisu MODELU COM může být volitelně převeden na návrat v podpisu jazyka C#.

Například následující fragmenty kódu zobrazují podpisy metod jazyka C# a odpovídající nativní podpis, který generátor odvodí.

void Method1(int i);

int Method2(float i);
HRESULT Method1(int i);

HRESULT Method2(float i, _Out_ int* returnValue);

Pokud chcete zpracovat HRESULT sami sebe, můžete pomocí PreserveSigAttribute metody naznačovat, že generátor by neměl tuto transformaci provést. Následující fragmenty kódu ukazují, jaký nativní podpis generátor očekává při [PreserveSig] použití. Metody COM musí vracet HRESULT, takže návratová hodnota libovolné metody s PreserveSig by měla být int.

[PreserveSig]
int Method1(int i, out int j);

[PreserveSig]
int Method2(float i);
HRESULT Method1(int i, int* j);

HRESULT Method2(float i);

Další informace naleznete v tématu Implicitní překlady podpisů metod v interoperability .NET

Nekompatibility a rozdíly mezi integrovanými modely COM

IUnknown pouze

Jedinou podporovanou základnou rozhraní je IUnknown. Rozhraní s InterfaceTypeAttribute jinou InterfaceIsIUnknown hodnotou než nejsou podporována ve zdrojovém vygenerovaném modelu COM. Všechna rozhraní bez předpokladu InterfaceTypeAttribute , že se odvozují od IUnknown. To se liší od integrovaného modelu COM, kde výchozí hodnota je InterfaceIsDual.

Přiřazování výchozích hodnot a podpory

Zdrojový objekt COM má několik různých výchozích chování při zařazování z integrovaného modelu COM.

  • V integrovaném systému COM mají všechny typy implicitní [In] atribut s výjimkou polí blittable elementů, které mají implicitní [In, Out] atributy. Ve zdrojovém modelu COM mají [In] všechny typy, včetně polí slittable prvků, sémantiku.

  • [In] a [Out] atributy jsou povoleny pouze u polí. Pokud [Out] nebo [In, Out] chování je požadováno u jiných typů, použijte in modifikátory a out parametry.

Odvozená rozhraní

Pokud máte rozhraní odvozená z jiných rozhraní MODELU COM, musíte deklarovat stínovací metodu pro každou základní metodu na základních rozhraních s klíčovým slovem new . Další informace naleznete v tématu Dědičnost rozhraní modelu COM a .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);
}

Generátor rozhraní MODELU COM neočekává žádné stínování základních metod. Pokud chcete vytvořit metodu, která dědí z jiného, jednoduše označte základní rozhraní jako základní rozhraní jazyka C# a přidejte metody odvozeného rozhraní. Další informace najdete v dokumentaci k návrhu.

[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);
}

Všimněte si, že rozhraní s atributem GeneratedComInterface může dědit pouze z jednoho základního GeneratedComInterface rozhraní, které má atribut.

Odvozená rozhraní přes hranice sestavení

V rozhraní .NET 8 není podporováno definování rozhraní s atributem GeneratedComInterfaceAttribute odvozeným z GeneratedComInterfacerozhraní -attributed, které je definováno v jiném sestavení.

V .NET 9 a novějších verzích se tento scénář podporuje s následujícími omezeními:

  • Základní typ rozhraní musí být zkompilován tak, aby cílová architektura byla stejná jako odvozený typ.
  • Základní typ rozhraní nesmí stínovat žádné členy jeho základního rozhraní, pokud ho má.

Kromě toho všechny změny vygenerovaných vygenerovaných virtuálních metod v řetězu základního rozhraní definovaném v jiném sestavení nebudou v odvozených rozhraních zohledněny, dokud se projekt znovu nevystaví.

Poznámka:

V rozhraní .NET 9 a novějších verzích se při dědění vygenerovaných rozhraní MODELU COM přes hranice sestavení generuje upozornění, které vás informuje o omezeních a nástrahách použití této funkce. Toto upozornění můžete zakázat, pokud chcete potvrdit omezení a dědit hranice sestavení.

Zařazování rozhraní API

Některá rozhraní API nejsou kompatibilní se zdrojovým vygenerovaným Marshal objektem COM. Tyto metody nahraďte odpovídajícími metodami implementace ComWrappers .

Viz také