1

I would like to have my classes exposed without displaying the base methods Equals(), GetHashCode(), GetType(), ToString(). I also want Intellisense to work properly. Here is my sample code:

using System;
using System.IO;
using System.Runtime.InteropServices;

namespace InteropTest
{
    [ClassInterface(ClassInterfaceType.AutoDual),
        ComVisible(true)]
    [ProgId("InteropTest.Wrapper")]
    public class Wrapper
    {
        public string Text1 = "hello";
        public string Text2 = "world";
        public Class1 Class1 = new Class1();
        public Class2 Class2 = new Class2();

    }

    [ClassInterface(ClassInterfaceType.AutoDual),
        ComVisible(true)]
    public class Class1
    {
        public string Method1a(string myText)
        {
            return myText;
        }

        public string Method1b(string myText)
        {
            return myText;
        }
    }

    [ClassInterface(ClassInterfaceType.AutoDual),
        ComVisible(true)]
    public class Class2
    {
        public string Method2a(string myText)
        {
            return myText;
        }

        public string Method2b(string myText)
        {
            return myText;
        }
    }
}

When I use [ClassInterface(ClassInterfaceType.None), ComVisible(true)], I can see the 2 properties in the Wrapper class, but I cannot see, nor access, Class1 or Class2.

When I use this class, I expect to be able to create the object and use it as well as see the appropriate Intellisense for the inner class objects.

o = CreateObject("InteropTest.Wrapper")
o.Class1.Method1a("Some text")

I guess, my real question is, how do I setup my classes for COM and make both Class1 and Class2 visible without displaying the extra methods?

I also tried using the refactor tool to extract the interfaces, but I could not get those to work the way I want to work, either. I don't want to put in any funky work-arounds, either.

9
  • Please edit your question and add a tag for the coding language you're using. Commented Jun 3, 2024 at 22:28
  • Your code works fine with .NET Framework 4 with VBScript client for example Set o = CreateObject("InteropTest.Wrapper") Wscript.echo o.Class1.Method1a("Some text"). As for hiding .NET methods you can hide ToString, Equals and GetHashCode if you just override them and add a ComVisible(false) attribute. Doesn't work for GetType though. If you really want that (why?) you'll have to use ClassInterfaceType.None and declare a ComInterfaceType.InterfaceIsDual interface instead. Commented Jun 4, 2024 at 6:32
  • @SimonMourier I am aware that the code works as is. The problem is that I would like to hide the 4 base methods. I am aware of the override hack, a funky work-around that is not complete, as you even mentioned. I don't want that. If I need to resort to using ClassInterfaceType.None, then how do I make the inner objects visible, i.e. Class1 and Class2 and their methods. Commented Jun 4, 2024 at 12:37
  • 1
    You should expose in your question what you know or already tested, it'll save everyone's time. Something like that should work pastebin.com/raw/GZ1nLuww Commented Jun 4, 2024 at 15:34
  • 1
    That's a normal mishap when you use [ClassInterface], it exposes all of the members of the class. Instead declare an interface and give it the [ComVisible] attribute. Then declare the class, inheriting that interface, also [ComVisible]. Same treatment on the other classes in the snippet. Don't expose the class as a return type, expose the interface instead. This also prevents the type library having a dependency on mscorlib.tlb Commented Jun 4, 2024 at 19:34

1 Answer 1

1

Using AutoDual on classes exposes every public method of the class automatically. To avoid that you can use AutoDual interfaces instead and implement it. Something like this should be equivalent:

[InterfaceType(ComInterfaceType.InterfaceIsDual), ComVisible(true)]
public interface IWrapper
{
    string Text1 { get; set; }
    string Text2 { get; set; }
    IClass1 Class1 { get; set; }
    IClass2 Class2 { get; set; }
}

[ClassInterface(ClassInterfaceType.None), ComVisible(true)]
[ProgId("InteropTest.Wrapper")]
public class Wrapper : IWrapper
{
    public string Text1 { get; set; } = "hello";
    public string Text2 { get; set; } = "world";
    public IClass1 Class1 { get; set; } = new Class1();
    public IClass2 Class2 { get; set; } = new Class2();
}

[InterfaceType(ComInterfaceType.InterfaceIsDual), ComVisible(true)]
public interface IClass1
{
    string Method1a(string myText);
    string Method1b(string myText);
}

[ClassInterface(ClassInterfaceType.None), ComVisible(true)]
public class Class1 : IClass1
{
    public string Method1a(string myText) => myText;
    public string Method1b(string myText) => myText;
}

[InterfaceType(ComInterfaceType.InterfaceIsDual), ComVisible(true)]
public interface IClass2
{
    string Method2a(string myText);
    string Method2b(string myText);
}

[ClassInterface(ClassInterfaceType.None), ComVisible(true)]
public class Class2 : IClass2
{
    public string Method2a(string myText) => myText;
    public string Method2b(string myText) => myText;
}

Note .NET fields have been replaced by .NET properties since you cannot define fields in interfaces, but at COM level it shouldn't change anything.

Sign up to request clarification or add additional context in comments.

1 Comment

This example also demonstrates how to expose a member class object, which is what I was really having a problem with. Thanks again.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.