Подтвердить что ты не робот

Почему маркировка сборки ComVisible (правда) обескуражена?

Я всегда отмечал свои сборки .NET как видимые для COM с [assembly: ComVisible(true)], думая, что я никогда не знаю, когда кому-то может потребоваться назвать их из COM. Я также начал использовать FxCop и начал видеть это предупреждение из анализа кода:

CA1017: Microsoft.Design: поскольку "MyLibrary.dll" раскрывает внешне видимые типы, отметьте его с помощью ComVisible (false) на уровне сборки и затем отметьте все типы внутри сборки, которые должны быть открыты COM-клиентам с помощью ComVisible (true )

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

4b9b3361

Ответ 1

Я не работал с COM-взаимодействием довольно долгое время, но в прошлом я всегда работал с философией "opt-in", а не "отказом", то есть вместо того, чтобы сделать все COM видимым, я отмечаю сборку как не COM видимый. Затем я сосредотачиваюсь на том, что вы выбираете типы \members выборочно (т.е. Выбираете) и убедитесь, что API, который подвергается воздействию, является нормальным для COM (например, COM не поддерживает Genrics, перегрузку метода или конструкторы, которые принимают параметры), а также что он имеет были протестированы с учетом COM. Таким образом, просмотр API для COM выполняется строго, проверенно, ограниченно и поддерживается.

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

Из памяти несколько примеров неожиданных последствий:

  • При экспорте перегруженных методов они экспортируются и называются по умолчанию с порядковым номером, например. OverloadedMethod1, OverloadedMethod2 и т.д. Если вы реорганизовываете свой код и изменяете порядок своих методов или вставляете перегрузку и т.д., У вас возникают проблемы с тем, кто использовал эти методы из вашего предыдущего COM-интерфейса. OverloadedMethod1 и OverloadedMethod2 могут быть заменены.

  • Классы, которые подвергаются воздействию COM, должны иметь конструктор без параметров. Если на этом контракте не существует unit test, который поддерживает этот контракт, то его легко изменить на более поздний срок, чтобы он не имел конструктора без параметров и, таким образом, нарушил пользователей вашего COM-интерфейса.

Ключевым моментом является то, что экспорт COM-интерфейса не предоставляется бесплатно, так как есть несовместимости и требования, которые должны быть выполнены. Об этом нужно думать и поддерживать. Предупреждение CA1017 ссылается на это.

Ответ 2

С появлением Generics и других продвинутых типов, более распространено сейчас, когда методы обнаруживают типы, которые не могут быть COM видимыми, чем для того, чтобы они могли выставлять типы, которые могут.

Рекомендуемый метод в CA1017 призван помочь вам разоблачить только те типы, которые вы намереваетесь подвергать COM.

Ответ 3

Для справки, если не применяется уровень сборки ComVisibleAttribute, все общедоступные классы считаются COM видимыми. Невозможность отметить сборку как [assembly: ComVisible(false)] часто приводит к следующему предупреждению анализа кода даже для типов, которые не отмечены [ComVisible(true)]:

CA1405: базовые типы видимого типа COM должны быть видимыми COM

Ответ 4

Маркировка сборки, а не видимая COM очень полезна когда у вас есть куча общедоступных классов внутри, которые вы не хотите показывать в COM. Эти классы могут быть, например, прокси-классами веб-сериализации, которые потребляет ваша сборка. Либо вы тщательно отмечаете каждый такой класс, а не COM видимый, или просто отмечаете сборку, а не COM, а затем отмечаете каждый класс, чтобы открыть COM. Это гораздо более высокая степень контроля и меньше обслуживания.

Ответ 5

Это легко и доступно на MSDN. Вот как это исправить:

using System;
using System.Runtime.InteropServices;

[assembly: ComVisible(false)]
namespace InteroperabilityLibrary
{
   [ComVisible(false)]
   public class BaseClass
   {
      public void SomeMethod(int valueOne) {}
   }

   // This class violates the rule.
   [ComVisible(true)] 
   public class DerivedClass : BaseClass
   {
      public void AnotherMethod(int valueOne, int valueTwo) {}
   }
}

Если базовый класс находится в любой DLL, которую вы ссылаетесь на свой код. Затем сделайте [COMVisibible (True)] для производного класса. Он работает по моему сценарию.