Up to now, I've always decorated my .NET classes that I want to use from VB6 with the [AutoDual]
attribute. The point was to gain Intellisense on .NET objects in the VB6 environment. However, the other day I googled AutoDual and the first answer is 'Do Not Use AutoDual'.
I've looked for coherent explanation of why I shouldn't use it, but could not find it.
Can someone here explain it?
I think this sums it up:
Types that use a dual interface allow
clients to bind to a specific
interface layout. Any changes in a
future version to the layout of the
type or any base types will break COM
clients that bind to the interface. By
default, if the
ClassInterfaceAttribute attribute is
not specified, a dispatch-only
interface is used.
http://msdn.microsoft.com/en-us/library/ms182205.aspx
It increases the possibility that changing something in that class with the auto dual attribute will break someone else's code when the class is changed. If gives the consumer the ability to do something that will quite possibly cause them issues in the future.
The next option is ClassInterfaceType.AutoDual. This is the quick and dirty way to get early binding support as well (and make the methods show up in VB6 IntelliSense). But it's also easy to break compatibility, by changing the order of methods or adding new overloads. Avoid using AutoDual.
http://www.dotnetinterop.com/faq/?q=ClassInterface
I finally found the link that talks about what is going on with AutoDual and how it works:
http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/7fa723e4-f884-41dd-9405-1f68afc72597
The warning against AutoDual isn't the
fact that dual interfaces is bad but
the fact that it auto-generates the
COM interface for you. That is bad.
Each time the COM interface has to be
regenerated you'll get a new GUID and
potentially new members. If the GUID
changes then you get a brand new
interface/class as far as COM is
concerned. For early binding you'd
have to rebuild the clients each time
the interface was regenerated. The
preferred approach is to define the
COM class interface explicitly with a
GUID. Then all the early binding
clients can use the defined interface
and not worry about it changing on
them during development. That is why
the recommended option is None to tell
the CLR not to auto-generate it for
you. You can still implement the dual
interface though if you need it.
I found a reliable way to both provide Intellisense for .NET objects in VB6, while at the same time not breaking the interface. The key is to mark each public method/property in the interface with DispatchID. Then the class must inherit from this interface - in the manner below.
[Guid("BE5E0B60-F855-478E-9BE2-AA9FD945F177")]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface ICriteria
{
[DispId(1)]
int ID { get; set; }
[DispId(2)]
string RateCardName { get; set; }
[DispId(3)]
string ElectionType { get; set; }
}
[Guid("3023F3F0-204C-411F-86CB-E6730B5F186B")]
[ClassInterface(ClassInterfaceType.None)]
[ProgId("MyNameSpace.Criteria")]
public class Criteria : ICriteria
{
public int ID { get; set; }
public string RateCardName { get; set; }
public string ElectionType { get; set; }
}
What the dispatch ID gives you is the ability to move around items in the class, plus you can now add new things to the class and not break the binary compatibility.