Search code examples
.netcomcomvisible

Export a method alias of COM visible .NET class


I have a construct of a .NET implementation of some utility and a .WSC script that instantiates the .NET object. The goal is to eliminate the WSCscript and to instantiate and call the .NET implementation directly. But this discovered a naming problem.

The class defined in the WSC contains several methods. One of these methods is Finalize(). The function name is reserved in .NET since it is used for the life time and GC management. Therefore the WSC calls a .NET function with a different name:

<?xml version="1.0"?>
<component>
  <public>
    <method name="Finalize"/>
  </public>
  <object id="wrapper" progid="JS.Wrapper"/>

  <script language="JScript">
    <![CDATA[
      // Processes last required steps and closes all logs
      function Finalize() {
         return wrapper.Finish();
      }
      // Any other function
      function Foo() {
        wrapper.Foo();
      }
    ]]>
  </script>
</component>

The .NET class implements the Finish function:

[ComVisible(true)]
[ProgId("JS.Wrapper")]
public class MyCom
{
    // Processes last required steps and closes all logs
    public void Finish()
    {
    }

    public void Foo()
    {
    }
}

There are thousands of scripts that call all the Foo() and Bar() functions. And most of them also calls the Finalize function. Therefore it is impossible to change the function name at the COM interface.

  • How can the function Finish be made COM-Visible with the name Finalize?
  • Is there a way to implement two Finalize functions, one for .NET run-time and one as exported at the COM interface.
  • Is it possible to implement a COM interface explicitly, i.e. make a custom implementation of the COM interface?

There is an attribute ComAliasName that can be used to make an property, indexer, field, param, or return visible with a an alias. But it can't be used for a method name. How can a method made visible as an alias?


Solution

  • The method Finalize can be exposed by defining explicitly the COM interface.

    public interface IMyCom
    {
        // Processes last required steps and closes all logs
        void Finalize();
        void Foo();
    }
    

    It's important to choose the ClassInterfaceType.None in the implementing .NET class. The implementation in the .NET class should specify the interface that is implemented. With the scope prefix IMyCom the compiler can distinguish between the name of the method at the COM interface and some .NET CLR internal names. The makes it unnecessary to use a different method name and to create an alias.

    [ComVisible(true)]
    [ProgId("JS.Wrapper")]
    [ClassInterface(ClassInterfaceType.None)]
    public class MyCom : IMyCom
    {
        // Explicitly specify the scope of the Finalize method.
        void IMyCom.Finalize()
        {
        }
    
        void IMyCom.Foo()
        {
        }
    }
    

    This approach makes it also clear that this is the implementation of a COM interface method.