3

我有现有的 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);

};
4

1 回答 1

8

您的 IDL 无效,归因于的接口[oleautomation]应派生自 IDispatch,而不是 IUnknown。我将给出正确的声明并提示您需要修改它们以获得您的声明。

You cannot declare indexed properties in C#, the C# team refuses to implement them. Version 4 has support for indexed properties that are declared in a COM type library but still doesn't allow declaring them yourself. The workaround is to use the VB.NET language, it has no qualms about it. Add a VB.NET class library project to your solution. Make it look similar to this:

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

Note the use of <DispId>, dispid 0 is special, it is the default property of an interface. This corresponds to the indexer in the C# language.

All you need VB.NET for is the declaration, you can still write the implementation of the interface in the C# language. Project + Add Reference, Projects tab and select the VB.NET project. Make it look similar to this:

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) {
        }
    }
}

You need to run Tlbexp.exe on both the VB.NET and the C# assembly to generate the type libraries. The C# one with the implementation includes the VB.NET one.

To get the interface to derive from IUnknown instead of IDispatch, edit the interface declaration. Remove the DispId attributes and use ComInterfaceType.InterfaceIsUnknown.

于 2011-06-23T12:01:09.663 回答