Reputation: 418
I have in existing COM-interface. I wan't to create a .net assembly that exposes a new interface as COM (with a new GUID), but the structure of the interface needs to be the same.
How can i create a .net class (C#) that exposes this interface?
[
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);
};
Upvotes: 3
Views: 1203
Reputation: 941317
Your IDL isn't valid, an interface that is attributed with [oleautomation]
should derive from IDispatch, not IUnknown. I'll give the proper declarations and hint where you need to modify them to get yours.
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
.
Upvotes: 8