Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why should I not use AutoDual?

Tags:

c#

.net-2.0

vb6

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?

like image 436
AngryHacker Avatar asked Apr 26 '10 14:04

AngryHacker


2 Answers

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.

like image 77
kemiller2002 Avatar answered Nov 15 '22 18:11

kemiller2002


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.

like image 41
AngryHacker Avatar answered Nov 15 '22 19:11

AngryHacker