2
votes

In a C# class library (.Net 3.5), I have a very simple class (some string and long properties, no methods) which inherit from System.Web.Services.Protocols.SoapHeader. My class is tagged as ComVisible(true) because I need to use it in Delphi.

For some unknown reason, this class can't be created in Delphi, when the class interface is automatically exported (aka attribute ClassInterface(ClassInterfaceType.AutoDispatch)). I made a simple C++ program to test about that, and I get each time the same error: 0x80131509 (Methods parameters or return type cannot be invoked via IDispatch). After some digging, the problem is directly related to SoapHeader. When I remove it or use it as property of my class, all run fine.

In C++, when using IDispatch to access my class exported with ClassInterfaceType.None, all work fine. But I can't relay on IDispatch in Delphi, so I'm searching a way to avoid the type library exporter to export SoapHeader stuff.

Is there a way to do that ? A .Net attribute to inform the type library exporter to avoid exposing a class parent ? To expose only a part of a class even if there is more stuff ?

1
What exactly did you intend to expose through the interface? Native COM interfaces (non-IDispatch) probably expect a non-empty vtable, and you have zero methods on it. So did you try adding methods named getProperty1' and getProperty2` instead of relying on properties to magically work without any vtable entries for the get property methods? - Warren P

1 Answers

4
votes

Declare an interface so you can explicitly name the members that are visible to COM clients. Like this:

using System;
using System.Runtime.InteropServices;

[ComVisible(true)]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface IThingsIWantToExpose {
    void mumble();
    // etc..
}

[ComVisible(true)]
[ClassInterface(ClassInterfaceType.None)]
public class MyComClass : SomeBaseClass, IThingsIWantToExpose {
    // Actual implementation of the methods
    public void mumble() { }
    // etc, plus everything else that you want to do in the class
    //...
}

Using ComInterfaceType.InterfaceIsDual allows both early and late binding (IDispatch). ClassInterfaceType.None hides the class members so the base class isn't exposed either. Including the System.Object members btw.