Aracılığıyla paylaş


ComWrappers için kaynak oluşturma

.NET 8, sizin için ComWrappers API'sinin bir uygulamasını oluşturan bir kaynak oluşturucuyu tanıtır . Oluşturucu, öğesini GeneratedComInterfaceAttributetanır.

.NET çalışma zamanının yerleşik (kaynak oluşturulmamış), yalnızca Windows, COM birlikte çalışma sistemi, yönetilen koddan COM'a geçişi kolaylaştırmak için çalışma zamanında bir IL saplaması (JIT-ed il yönergeleri akışı) oluşturur ve tam tersi de geçerlidir. Bu IL saplaması çalışma zamanında oluşturulduğundan NativeAOT ve IL kırpma ile uyumlu değildir. Çalışma zamanında saplama oluşturma, marshalling sorunlarını tanılamayı da zorlaştırabilir.

Yerleşik birlikte çalışma, çalışma zamanında kod oluşturmayı kullanan veya DllImportgibi ComImport öznitelikleri kullanır. Aşağıdaki kodda bunun bir örneği gösterilmektedir:

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

API, ComWrappers yerleşik COM sistemini kullanmadan C# dilinde COM ile etkileşime olanak tanır, ancak önemli ölçüde ortak ve el ile yazılmış güvenli olmayan kod gerektirir. COM arabirim oluşturucu bu işlemi otomatikleştirir ve yerleşik COM kadar kolay hale getirir ComWrappers , ancak kırpılabilir ve AOT dostu bir şekilde sunar.

Temel kullanım

COM arabirim oluşturucuyu kullanmak için, com'dan içeri aktarmak veya COM'a göstermek istediğiniz arabirim tanımına ve GuidAttribute özniteliklerini ekleyinGeneratedComInterfaceAttribute. Türün işaretlenmesi partial ve oluşturulan koda erişebilmesi için veya görünürlüğüne sahip internalpublic olması gerekir.

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

Ardından, COM'a arabirim uygulayan bir sınıfı kullanıma açmak için öğesini uygulayan sınıfa ekleyin GeneratedComClassAttribute . Bu sınıf da ve internal veya publicolmalıdırpartial.

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

Derleme zamanında, oluşturucu ComWrappers API'sinin bir uygulamasını oluşturur ve COM arabirimini kullanmak veya kullanıma açmak için türünü veya özel türetilmiş bir türü kullanabilirsiniz StrategyBasedComWrappers .

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

Sıralamayı özelleştirme

COM arabirim oluşturucu, parametrelerin sıralamasını MarshalUsingAttribute özelleştirmek için özniteliğine MarshalAsAttribute ve özniteliğin bazı kullanımlarına uyar. Daha fazla bilgi için bkz. kaynak tarafından oluşturulan sıralamayı MarshalUsing özniteliğiyle özelleştirme ve özniteliğiyle parametre hazırlamayı MarshalAs özelleştirme. GeneratedComInterfaceAttribute.StringMarshalling ve GeneratedComInterfaceAttribute.StringMarshallingCustomType özellikleri tüm parametrelere uygulanır ve diğer sıralama öznitelikleri yoksa arabirimdeki tür string türlerini döndürür.

Örtük HRESULTs ve PreserveSig

C# içindeki COM yöntemleri, yerel yöntemlerden farklı bir imzaya sahiptir. Standart COM, hata ve başarı durumlarını HRESULTtemsil eden 4 baytlık tamsayı türünde bir dönüş türüne sahiptir. Bu HRESULT dönüş değeri varsayılan olarak C# imzasında gizlenir ve bir hata değeri döndürüldüğünde özel duruma dönüştürülür. Yerel COM imzasının son "out" parametresi isteğe bağlı olarak C# imzasında dönüşe dönüştürülebilir.

Örneğin, aşağıdaki kod parçacıkları C# yöntemi imzalarını ve oluşturucunun çıkarımlarını ilgili yerel imzayı gösterir.

void Method1(int i);

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

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

Kendiniz işlemek HRESULT istiyorsanız, oluşturucunun PreserveSigAttribute bu dönüşümü yapmaması gerektiğini belirtmek için yöntemini kullanabilirsiniz. Aşağıdaki kod parçacıkları, oluşturucu uygulandığında [PreserveSig] hangi yerel imzanın beklediğini gösterir. COM yöntemleri döndürmelidir HRESULT, bu nedenle ile PreserveSig herhangi bir yöntemin dönüş değeri olmalıdır int.

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

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

HRESULT Method2(float i);

Daha fazla bilgi için bkz. .NET birlikte çalışmasında örtük yöntem imza çevirileri

Yerleşik COM ile uyumsuzluklar ve farklılıklar

IUnknown Sadece

Desteklenen tek arabirim tabanıdır IUnknown. dışında bir değere InterfaceIsIUnknown sahip arabirimlerInterfaceTypeAttribute, kaynak tarafından oluşturulan COM'da desteklenmez. olmayan InterfaceTypeAttribute tüm arabirimlerin'den IUnknowntüretilmiş olduğu varsayılır. Bu, varsayılanın InterfaceIsDualolduğu yerleşik COM'dan farklıdır.

Varsayılanları ve desteği hazırlama

Kaynak tarafından oluşturulan COM,yerleşik COM'dan bazı farklı varsayılan sıralama davranışlarına sahiptir.

  • Yerleşik COM sisteminde, örtük [In] özniteliklere sahip olan blittable öğe dizileri dışında tüm türler örtük [In, Out] bir özniteliğe sahiptir. Kaynak tarafından oluşturulan COM'da, kesilebilir öğe dizileri de dahil olmak üzere tüm türlerin semantiği vardır [In] .

  • [In] ve [Out] özniteliklerine yalnızca dizilerde izin verilir. [Out] Diğer türlerde veya [In, Out] davranışı gerekiyorsa ve out parametre değiştiricilerini in kullanın.

Türetilmiş arabirimler

Yerleşik COM sisteminde, diğer COM arabirimlerinden türetilen arabirimleriniz varsa, anahtar sözcüğüyle new temel arabirimlerde her temel yöntem için bir gölgelendirme yöntemi bildirmeniz gerekir. Daha fazla bilgi için bkz . COM arabirimi devralma ve .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);
}

COM arabirim oluşturucu, temel yöntemlerin gölgelendirmesini beklemez. Başka bir arabirimden devralan bir yöntem oluşturmak için, temel arabirimi bir C# temel arabirimi olarak belirtmeniz ve türetilmiş arabirimin yöntemlerini eklemeniz yeterlidir. Daha fazla bilgi için tasarım belgesine bakın.

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

özniteliğine sahip bir arabirimin GeneratedComInterface yalnızca özniteliği olan GeneratedComInterface bir temel arabirimden devralabileceğini unutmayın.

API'leri hazırlama

içindeki Marshal bazı API'ler kaynak tarafından oluşturulan COM ile uyumlu değildir. Bu yöntemleri bir ComWrappers uygulamadaki ilgili yöntemleriyle değiştirin.

Ayrıca bkz.