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ý HRESULT
typ , 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žijtein
modifikátory aout
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 GeneratedComInterface
rozhraní -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
.