2010-04-26 4 views
7

До сих пор я всегда украшал свои классы .NET, которые я хочу использовать из VB6 с атрибутом [AutoDual]. Дело в том, чтобы получить Intellisense на объектах .NET в среде VB6. Однако на днях я googled AutoDual, и первым ответом является «Не использовать AutoDual».Почему я не должен использовать AutoDual?

Я искал последовательное объяснение, почему я не должен его использовать, но не смог найти его.

Может кто-то здесь объяснить это?

ответ

8

Я думаю, что это подводит итог:

Типов, которые используют двойной интерфейс позволяют клиентам связываться с конкретной компоновкой интерфейса. Любые изменения в будущей версии на макет типа или любых базовых типов прерывают клиенты COM , которые привязываются к интерфейсу. По умолчанию , если атрибут ClassInterfaceAttribute не указан, используется интерфейс только для отправки .

http://msdn.microsoft.com/en-us/library/ms182205.aspx

Это увеличивает вероятность того, что что-то изменить в этом классе с автоматическим двойным атрибутом сломается чужого кода при изменении класса. Если дает потребителю возможность сделать что-то, что вполне может вызвать их проблемы в будущем.

Следующая опция - ClassInterfaceType.AutoDual. Это быстрый и грязный способ получить поддержку раннего связывания (и заставить методы появляться в VB6 IntelliSense). Но также легко нарушить совместимость, изменив порядок методов или добавив новые перегрузки. Избегайте использования AutoDual.

http://www.dotnetinterop.com/faq/?q=ClassInterface

Я наконец-то нашел ссылку, которая говорит о том, что происходит с автодуальна и как он работает:

http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/7fa723e4-f884-41dd-9405-1f68afc72597

Предупреждение против автодуальна не факт, что два интерфейса плохо, но факт, что он автоматически создает COM-интерфейс для вас. Это плохо. Каждый раз, когда COM-интерфейс должен быть восстановлен, вы получите новый GUID и потенциально новых членов. Если GUID изменяется, то вы получаете совершенно новый интерфейс/класс , поскольку COM - . Для раннего связывания вам необходимо будет восстанавливать клиентов , после чего восстанавливается интерфейс. Предпочтительным подходом является определение интерфейса класса COM явно с помощью GUID . Тогда все ранние связывающие клиенты могут использовать определенный интерфейс и не беспокоиться об этом, изменяя их на их во время разработки. Вот почему рекомендуемый параметр: None, чтобы сообщить CLR, чтобы не автогенерировать его для вас. Вы все равно можете реализовать двойной интерфейс , хотя, если вам это нужно.

+0

Часть, о которой я не знаю, гласит следующее: «Любые изменения в будущей версии макета типа или любых базовых типов будут прерывать COM-клиенты». Значение, если я изменю свойство от int до double, клиент сломается? Или это означает, что если я просто перекомпилирую часть .NET, клиент VB6 больше не сможет ее использовать? – AngryHacker

+0

Пока вы не меняете интерфейс, вы должны быть в порядке. http://www.dotnetinterop.com/faq/?q=ClassInterface – kemiller2002

+0

@Kevin, поэтому просто перекомпилировать мою библиотеку .NET не сломает потребитель, чем? И что означает «изменение порядка методов»? Смысл изменить порядок методов в коде? Я до сих пор не понимаю, почему мы должны избегать AutoDual. Я думаю, что понятно, что если вы измените интерфейс, то потребитель не будет работать. Это почти всегда было в мире VB6. – AngryHacker

11

Я нашел надежный способ предоставить объекты Intellisense для .NET в VB6 и в то же время не нарушать интерфейс. Ключ состоит в том, чтобы пометить каждый открытый метод/свойство в интерфейсе с DispatchID. Затем класс должен наследовать от этого интерфейса - следующим образом.

[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; } 
} 

Что диспетчерская ID дает вам это способность двигаться предметы в классе, плюс теперь вы можете добавлять новые вещи в классе и не нарушать бинарную совместимость.

Смежные вопросы