Practices For - Building .NET Type Compatible COM Classes

While Building .NET Type compatible COM Classes we need to practice some of the following steps for better effectiveness. Let us have a closer-analysis of these practices. I am aware of 3 practices that I would like to share Practice #1 - Do not Indirectly Implement the Same Interface Twice

 

First, understand that a given RCW automatically simulates a small handful of .NET interfaces depending on the composition of the coclass. Specifically,

 

§            IEnumerable will be supported for COM classes that support a member with the DISPID of -4 (i.e., the  DISPID_NEWENUM value used when building COM collections).

 

§            IExpando will be supported for coclasses implementing IDispatchEx.

 

§            IReflect will be supported for objects implementing ITypeInfo.

Given that the RCW will simulate such interfaces without effort on your part, it makes sense that you should never manually implement the same interface on a given COM type. In fact, if you do, the interop assembly incorrectly implements the same interface twice (causing massive chaos). The truth of the matter is, few COM programmers directly implement IDispatchEx or ITypeInfo in the first place, so this should not be too much of an issue. However, do make sure that when you build a COM collection you don't implement the .NET IEnumerable interface on the same type.

 

 

Practice #2 - Do not  Implement .NET Class Interfaces

The second commonsense practices has to do with implementing autogenerated "class interfaces.when a .NET type is converted to a corresponding COM type definition, a class may make use of a class interface to establish a [default] interface for the type. Simply put, a class interface is the summation of each public member on the .NET class (as well as each public member up the chain of inheritance). By convention, class interfaces are always named _NameOfTheClass.

 For example, the class interface of System.Object is _Object. MyCoolDotNetClass produces a class interface named _MyCoolDotNetClass and so on.

Understand that you gain nothing if you implement an autogenerated class interface on a given COM class because the .NET type system does not honor the definition or use of class interfaces in the first place! If you implement a class interface on a given COM type, it would not be type compatible with original .NET type. By way of a simple example, assume that you have the following .NET class definition:

 

using System;

using System.Runtime.InteropServices;

 

namespace MyClassInterfaceLibrary

{

  [ClassInterface(ClassInterfaceType.AutoDual)]

  public class DotNetClass

  {

    public DotNetClass(){}

    public void Foo(){}

  }

}

 

 

Without getting too bogged down in the details at this point, simply understand that the ClassInterfaceAttribute  type is used to instruct how to expose a .NET class to COM. By specifying ClassInterfaceType.AutoDual, you are instructing tlbexp.exe to expose this class type as a [dual] COM interface named _DotNetClass. Once this assembly is converted into a related COM type library (via tlbexp.exe), you find the following IDL definition:

 

   interface _DotNetClass : IDispatch

{

  // Inherited System.Object members removed for clarity

  HRESULT Foo();

};

coclass DotNetClass

{

  [default] interface _DotNetClass;

  interface _Object;

};

 

As you can see, the generated coclass supports the class interface _DotNetClass as the [default], and therefore a VB 6.0 COM client could call the Foo() method as follows:

 

' VB 6.0 calling Foo() on a .NET class.

Dim f as DotNetClass

Set f = New DotNetClass

f.Foo

Now, what if the same VB 6.0 application implemented this class interface on a given COM type? It could be done given that _DotNetClass has been published into the COM type information. Assume you have a coclass named CoIWannaBeLikeYou, which is defined as follows (recall that VB 6.0 hides underscore prefixes):

 

' Inherited System.Object members removed for clarity

Option Explicit

Implements DotNetClass

Private Sub DotNetClass_Foo()

  ' Stuff

End Sub

Here's the important question:

 "Could a managed client application treat the original .NET DotNetClass type and the VB 6.0 CoIWannaBeLikeYou identically?" The answer is a resounding "No." When a managed client creates the native .NET type, it is working with a direct object reference (the class interface is nonexistent). When the managed client creates an instance of the COM class, it is pointing to an interface named _DotNetClass. Thus, if the managed client defined a method such as

 

public void WorkWithDotNetClass(DotNetClass x)

{ x.Foo();}

the two types could not be treated polymorphically, given that the _DotNetClass interface is not the same as a DotNetClass object reference! The bottom line is that class interfaces are only meaningful by an unmanaged COM client. If a coclass implements a class interface, it is most certainly not type compatible with the .NET class that produced it (so don't bother to do so).

 

 

Practice #3 –  Limitation in VB6.0

Visual Basic 6.0 has a rather annoying behavior when it comes to the act of implementing interfaces: It is unable to implement interfaces that contain members named using an underbar (for example, My_Method(), My_Other_Method(), HereAreThreeUnderbars___(), and so on). Assume a COM interface defined in IDL as follows:

 

interface IFoo : IDispatch

{

    [id(1), helpstring("method Hello_There")]

    HRESULT Hello_There();

};

If you implement the IFoo interface on a VB 6.0 coclass, you would not be able to provide programming logic for Hello_There().

While it might not be the case that you will ever build a COM method using this rather old-fashioned naming convention, recall that when tlbimp.exe encounters a type that defines overloaded methods, it disambiguates each version using an underbar (i.e., Method_1(), Method_2(), and so on). Given these facts, understand that you cannot build a .NET type compatible COM class using VB 6.0 if the interface in question defines overloaded members.

 

Hope this practices helps you in the process of Application development.

Hide comments

Comments

  • Allowed HTML tags: <em> <strong> <blockquote> <br> <p>

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.
Publish