Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
.NET 8 zavádí zdrojový generátor, který za vás vytvoří implementaci rozhraní API ComWrappers . Generátor rozpozná GeneratedComInterfaceAttribute.
Modul .NET runtime, který není generován ze zdroje, systém interoperability COM pouze pro Windows, generuje zástupný IL stub – tok instrukcí IL, který je překládán 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 IL stub generuje za běhu, není kompatibilní s NativeAOT a ořezáváním IL. Generování stubů za běhu může také ztížit diagnostiku problémů s marshallingem.
Vestavěná interoperabilita používá atributy, jako jsou ComImport nebo DllImport, které spoléhají na generování kódu za běhu programu. 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ý objem šablonovitého a ručně psaného nebezpečného kódu. Generátor rozhraní COM tento proces automatizuje a usnadňuje ComWrappers stejně snadno jako vestavěné COM, ale poskytuje to v ořezatelném a AOT-přívětivém formátu.
Základní použití
Pokud chcete použít generátor rozhraní COM, přidejte atributy GeneratedComInterfaceAttribute a GuidAttribute do definice rozhraní, kterou chcete importovat z COM nebo zpřístupnit pro COM. Typ musí být označený partial a mít viditelnost internal nebo public, aby k němu měl vygenerovaný kód 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 také partial a buď internal nebo public.
[GeneratedComClass]
internal partial class Foo : IFoo
{
public void Method(int i)
{
// Do things
}
}
Generátor při kompilaci vytvoří implementaci rozhraní COMWrappers a můžete použít typ StrategyBasedComWrappers nebo vlastní odvozený typ k využívá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í COM zohledňuje atribut MarshalUsingAttribute a některá použití atributu MarshalAsAttribute k přizpůsobení zpracování parametrů. Další informace najdete o přizpůsobení zdrojového generovaného přenosu pomocí atributu MarshalUsing a o přizpůsobení přenosu parametrů pomocí atributu MarshalAs. Vlastnosti GeneratedComInterfaceAttribute.StringMarshalling a GeneratedComInterfaceAttribute.StringMarshallingCustomType platí pro všechny parametry a návratové typy typu string v rozhraní, pokud nemají jiné marshallingové atributy.
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" v nativním podpisu COM může být volitelně převeden na návratový typ 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, můžete použít metodu PreserveSigAttribute k označení, ž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 rozhraní .NET interop.
Nekompatibility a rozdíly oproti vestavěnému COM
IUnknown pouze
Jedinou podporovanou základnou rozhraní je IUnknown. Rozhraní s InterfaceTypeAttribute hodnotou, která není InterfaceIsIUnknown, není podporováno ve vygenerovaném ze zdroje COM. Rozhraní bez InterfaceTypeAttribute se považují za odvozená z IUnknown. To se liší od integrovaného modelu COM, kde výchozí hodnota je InterfaceIsDual.
Usměrňování výchozích hodnot a podpora
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ě generovaném COM mají všechny typy, včetně polí prvků typu blittable,[In]sémantiku.[In]a[Out]atributy jsou povoleny pouze u polí. Pokud je požadováno chování[Out]nebo[In, Out]u jiných typů, použijte modifikátory parametrůinaout.
Odvozená rozhraní
Pokud máte rozhraní odvozená z jiných rozhraní COM v vestavěném systému COM, musíte deklarovat stínovací metodu pro každou základní metodu v 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 .NET 8 není podporováno definování rozhraní s atributem GeneratedComInterfaceAttribute, které je odvozeno z rozhraní s atributem GeneratedComInterface definovaného 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á.
Navíc žádné změny odsazení vygenerovaných virtuálních metod v řetězci základního rozhraní definovaném v jiném sestavení nebudou brány v úvahu v odvozených rozhraních, dokud nebude projekt znovu sestaven.
Poznámka:
V .NET 9 a novějších verzích se při dědění generovaných rozhraní COM přes hranice sestavení, generuje upozornění, které vás informuje o omezeních a nástrahách použití této funkce. Můžete toto upozornění vypnout, abyste uznali omezení a umožnili dědění přes hranice sestavení.
Zařazování rozhraní API
Některá API v Marshal nejsou kompatibilní se zdrojově generovaným COM. Tyto metody nahraďte odpovídajícími metodami implementace ComWrappers .