将类似索引器的属性暴露给COM

Sør*_*rup 2 c# idl com-interop

我有现有的COM接口.我不想创建一个将新接口公开为COM(带有新GUID)的.net程序集,但接口的结构必须相同.

如何创建一个公开此接口的.net类(C#)?

[
  odl,
  uuid(1ED4C594-DDD7-402F-90DE-7F85D65560C4),
  hidden,
  oleautomation
]
interface _IFlashPhase : IUnknown {

    [propget]
    HRESULT _stdcall ComponentName(
                    [in] short i, 
                    [out, retval] BSTR* pVal);
    [propput]
    HRESULT _stdcall ComponentName(
                    [in] short i, 
                    [in] BSTR pVal);
    [propget]
    HRESULT _stdcall ComponentMolePercent(
                    [in] short i, 
                    [out, retval] double* pVal);
    [propput]
    HRESULT _stdcall ComponentMolePercent(
                    [in] short i, 
                    [in] double pVal);
    [propget]
    HRESULT _stdcall ComponentFugacity(
                    [in] short i, 
                    [out, retval] double* pVal);
    [propput]
    HRESULT _stdcall ComponentFugacity(
                    [in] short i, 
                    [in] double pVal);

};
Run Code Online (Sandbox Code Playgroud)

Han*_*ant 7

您的IDL无效,属于[oleautomation]的接口应该来自IDispatch,而不是IUnknown.我将给出适当的声明和提示,你需要修改它们以获得你的声明.

您无法在C#中声明索引属性,C#团队拒绝实现它们.版本4支持在COM类型库中声明但仍不允许自己声明它们的索引属性.解决方法是使用VB.NET语言,它没有任何疑虑.将VB.NET类库项目添加到您的解决方案中.使它看起来类似于:

Imports System.Runtime.InteropServices

Namespace Mumble

    <ComVisible(True)> _
    <Guid("2352FDD4-F7C9-443a-BC3F-3EE230EF6C1B")> _
    <InterfaceType(ComInterfaceType.InterfaceIsDual)> _
    Public Interface IExample
        <DispId(0)> _
        Property Indexer(ByVal index As Integer) As Integer
        <DispId(1)> _
        Property SomeProperty(ByVal index As Integer) As String
    End Interface

End Namespace
Run Code Online (Sandbox Code Playgroud)

注意使用<DispId>,dispid 0是特殊的,它是接口的默认属性.这对应于C#语言中的索引器.

所有你需要的VB.NET都是声明,你仍然可以用C#语言编写接口的实现.Project + Add Reference,Projects选项卡并选择VB.NET项目.使它看起来类似于:

using System;
using System.Runtime.InteropServices;

namespace Mumble {
    [ComVisible(true)]
    [Guid("8B72CE6C-511F-456e-B71B-ED3B3A09A03C")]
    [ClassInterface(ClassInterfaceType.None)]
    public class Implementation : ClassLibrary2.Mumble.IExample {
        public int get_Indexer(int index) {
            return index;
        }
        public void set_Indexer(int index, int Value) {
        }

        public string get_SomeProperty(int index) {
            return index.ToString();
        }

        public void set_SomeProperty(int index, string Value) {
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

您需要在运行Tlbexp.exe 在VB.NET和C#组件产生的类型库.实现的C#包括VB.NET.

要使接口从IUnknown而不是IDispatch派生,请编辑接口声明.删除DispId属性并使用ComInterfaceType.InterfaceIsUnknown