为什么标记装配ComVisible(true)气馁?

时间:2022-04-04 20:59:21

I have always marked my .NET assemblies as visible to COM with [assembly: ComVisible(true)], thinking that I never know when someone might need to call them from COM. I also started using FxCop and started seeing this warning from code analysis:

我总是使用[assembly:ComVisible(true)]标记我的.NET程序集对COM是可见的,以为我从来不知道有人可能需要从COM调用它们。我也开始使用FxCop并开始从代码分析中看到这个警告:

CA1017 : Microsoft.Design : Because 'MyLibrary.dll' exposes externally visible types, mark it with ComVisible(false) at the assembly level and then mark all types within the assembly that should be exposed to COM clients with ComVisible(true)

CA1017:Microsoft.Design:因为“MyLibrary.dll”公开了外部可见类型,所以在程序集级别使用ComVisible(false)标记它,然后使用ComVisible标记应该向COM客户端公开的程序集中的所有类型(true)

Is there some reason why you would not simply want all of your public types exposed to COM? I'm guessing that there is, but I cannot imagine what this reason is. If anything, it seems markedly inconvenient.

您是否有理由不想让所有公共类型都暴露给COM?我猜这有,但我无法想象这是什么原因。如果有的话,它似乎非常不方便。

5 个解决方案

#1


24  

I have not worked with COM interop for quite some time, but in the past I have always worked with the "opt-in" philosophy rather than "opt-out" i.e. rather than making everything COM visible, I mark the assembly as not COM visible. I then concentrate on exposing types\members selectively (i.e. by opting in), and make sure that the API that is exposed is sane for COM (e.g. COM does not support Genrics, method overloading or constructors which take parameters) and also that it has been tested with COM in mind. In this way exposing an API to COM is done in a rigorous, tested, bounded and maintainable fashion.

我有一段时间没有使用COM互操作,但过去我一直使用“选择加入”的理念,而不是“选择退出”,而不是让所有COM都可见,我将程序集标记为不COM可见。然后我专注于有选择地暴露types \ members(即通过选择),并确保暴露的API对于COM是理智的(例如COM不支持Genrics,方法重载或带有参数的构造函数)以及它具有已经考虑过COM的测试。通过这种方式,将API暴露给COM是以严格的,经过测试的,有界的和可维护的方式完成的。

This is the opposite to making everything COM visible and then worrying about any potential issues later, bearing in mind that if you have exposed everything then there may be couplings with users of your COM interface that you did not expect and will now have difficulty backing out of.

这与使所有COM可见并且随后担心任何潜在问题相反,请记住,如果您已经暴露了所有内容,那么可能会与COM接口的用户进行耦合,这是您没想到的并且现在将难以退出的。

From memory a couple of examples of unexpected consequences:

从记忆中可以看出一些意想不到的后果:

  1. When exporting overloaded methods, they are exported and named by default with a sequence number e.g. OverloadedMethod1, OverloadedMethod2, etc. If you refactor your code and change the order of your methods or insert an overload, etc, you are then in trouble with anyone that has used these methods from your previous COM interface. OverloadedMethod1 and OverloadedMethod2 may have been swapped.

    导出重载方法时,默认情况下会导出它们并使用序列号命名,例如OverloadedMethod1,OverloadedMethod2等。如果您重构代码并更改方法的顺序或插入重载等,那么您在之前的COM接口中使用这些方法的任何人都会遇到麻烦。 OverloadedMethod1和OverloadedMethod2可能已被交换。

  2. Classes which are exposed to COM must have a parameterless constructor. If there is not a unit test in place that maintains this contract, then it is easy to change that class at a later date so that it does not have a parameterless constructor and thus breaks your COM interface users.

    暴露给COM的类必须具有无参数构造函数。如果没有维护此合同的单元测试,则可以在以后更改该类,以便它没有无参数构造函数,从而破坏了COM接口用户。

The key thing is that exporting a COM interface does not come for free as there are incompatibilities and requirements that must be met. This has to be both thought about and then maintained. Warning CA1017 is alluding to this.

关键是导出COM接口不是免费的,因为必须满足不兼容性和要求。必须考虑并保持这一点。警告CA1017暗指这一点。

#2


5  

With the advent of Generics and other advanced types, it is more common now for methods to expose types that can't be COM visible than it is for them to expose types that can.

随着泛型和其他高级类型的出现,现在更常见的方法是公开不能COM可见的类型,而不是公开可以公开的类型。

The recommended method in CA1017 is intended to encourage you to expose only those types that you intend to be exposed to COM.

CA1017中推荐的方法旨在鼓励您仅公开那些您打算向COM公开的类型。

#3


5  

For reference, if no assembly level ComVisibleAttribute is applied, all public classes are assumed to be COM Visible. Failing to mark an assembly as [assembly: ComVisible(false)] will often result in the following Code Analysis warning, even for types that are not marked [ComVisible(true)]:

作为参考,如果未应用任何程序集级别的ComVisibleAttribute,则假定所有公共类都是COM Visible。未能将程序集标记为[assembly:ComVisible(false)]通常会导致以下代码分析警告,即使对于未标记为[ComVisible(true)]的类型也是如此:

CA1405: COM visible type base types should be COM visible

CA1405:COM可见类型基类型应该是COM可见的

#4


2  

Marking the assembly not COM visible is very useful when you have a bunch of public classes inside that you don't want to expose to COM. Those classes could for example be proxy classes of a web serive your assembly consumes. Either you thoroughly mark each such class not COM visible or you just mark the assembly not COM visble and then mark each class to expose to COM. That's a much higher degree of control and less maintenance.

当你有一堆你不希望暴露给COM的公共类时,标记程序集而不是COM可见是非常有用的。例如,这些类可以是程序集消耗的Web服务的代理类。要么彻底标记每个这样的类而不是COM可见,要么只是标记程序集而不是COM可见,然后标记每个类以向COM公开。这是一个更高程度的控制和更少的维护。

#5


1  

It is easy and given on MSDN. This is the way how to fix this warning:

这很简单,并在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) {}
   }
}

If Base class is in any dll which you are referring in your code. Then, Make [COMVisibible(True)] for derived class. It works in my scenario.

如果Base类在您的代码中引用的任何dll中。然后,为派生类创建[COMVisibible(True)]。它适用于我的场景。

#1


24  

I have not worked with COM interop for quite some time, but in the past I have always worked with the "opt-in" philosophy rather than "opt-out" i.e. rather than making everything COM visible, I mark the assembly as not COM visible. I then concentrate on exposing types\members selectively (i.e. by opting in), and make sure that the API that is exposed is sane for COM (e.g. COM does not support Genrics, method overloading or constructors which take parameters) and also that it has been tested with COM in mind. In this way exposing an API to COM is done in a rigorous, tested, bounded and maintainable fashion.

我有一段时间没有使用COM互操作,但过去我一直使用“选择加入”的理念,而不是“选择退出”,而不是让所有COM都可见,我将程序集标记为不COM可见。然后我专注于有选择地暴露types \ members(即通过选择),并确保暴露的API对于COM是理智的(例如COM不支持Genrics,方法重载或带有参数的构造函数)以及它具有已经考虑过COM的测试。通过这种方式,将API暴露给COM是以严格的,经过测试的,有界的和可维护的方式完成的。

This is the opposite to making everything COM visible and then worrying about any potential issues later, bearing in mind that if you have exposed everything then there may be couplings with users of your COM interface that you did not expect and will now have difficulty backing out of.

这与使所有COM可见并且随后担心任何潜在问题相反,请记住,如果您已经暴露了所有内容,那么可能会与COM接口的用户进行耦合,这是您没想到的并且现在将难以退出的。

From memory a couple of examples of unexpected consequences:

从记忆中可以看出一些意想不到的后果:

  1. When exporting overloaded methods, they are exported and named by default with a sequence number e.g. OverloadedMethod1, OverloadedMethod2, etc. If you refactor your code and change the order of your methods or insert an overload, etc, you are then in trouble with anyone that has used these methods from your previous COM interface. OverloadedMethod1 and OverloadedMethod2 may have been swapped.

    导出重载方法时,默认情况下会导出它们并使用序列号命名,例如OverloadedMethod1,OverloadedMethod2等。如果您重构代码并更改方法的顺序或插入重载等,那么您在之前的COM接口中使用这些方法的任何人都会遇到麻烦。 OverloadedMethod1和OverloadedMethod2可能已被交换。

  2. Classes which are exposed to COM must have a parameterless constructor. If there is not a unit test in place that maintains this contract, then it is easy to change that class at a later date so that it does not have a parameterless constructor and thus breaks your COM interface users.

    暴露给COM的类必须具有无参数构造函数。如果没有维护此合同的单元测试,则可以在以后更改该类,以便它没有无参数构造函数,从而破坏了COM接口用户。

The key thing is that exporting a COM interface does not come for free as there are incompatibilities and requirements that must be met. This has to be both thought about and then maintained. Warning CA1017 is alluding to this.

关键是导出COM接口不是免费的,因为必须满足不兼容性和要求。必须考虑并保持这一点。警告CA1017暗指这一点。

#2


5  

With the advent of Generics and other advanced types, it is more common now for methods to expose types that can't be COM visible than it is for them to expose types that can.

随着泛型和其他高级类型的出现,现在更常见的方法是公开不能COM可见的类型,而不是公开可以公开的类型。

The recommended method in CA1017 is intended to encourage you to expose only those types that you intend to be exposed to COM.

CA1017中推荐的方法旨在鼓励您仅公开那些您打算向COM公开的类型。

#3


5  

For reference, if no assembly level ComVisibleAttribute is applied, all public classes are assumed to be COM Visible. Failing to mark an assembly as [assembly: ComVisible(false)] will often result in the following Code Analysis warning, even for types that are not marked [ComVisible(true)]:

作为参考,如果未应用任何程序集级别的ComVisibleAttribute,则假定所有公共类都是COM Visible。未能将程序集标记为[assembly:ComVisible(false)]通常会导致以下代码分析警告,即使对于未标记为[ComVisible(true)]的类型也是如此:

CA1405: COM visible type base types should be COM visible

CA1405:COM可见类型基类型应该是COM可见的

#4


2  

Marking the assembly not COM visible is very useful when you have a bunch of public classes inside that you don't want to expose to COM. Those classes could for example be proxy classes of a web serive your assembly consumes. Either you thoroughly mark each such class not COM visible or you just mark the assembly not COM visble and then mark each class to expose to COM. That's a much higher degree of control and less maintenance.

当你有一堆你不希望暴露给COM的公共类时,标记程序集而不是COM可见是非常有用的。例如,这些类可以是程序集消耗的Web服务的代理类。要么彻底标记每个这样的类而不是COM可见,要么只是标记程序集而不是COM可见,然后标记每个类以向COM公开。这是一个更高程度的控制和更少的维护。

#5


1  

It is easy and given on MSDN. This is the way how to fix this warning:

这很简单,并在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) {}
   }
}

If Base class is in any dll which you are referring in your code. Then, Make [COMVisibible(True)] for derived class. It works in my scenario.

如果Base类在您的代码中引用的任何dll中。然后,为派生类创建[COMVisibible(True)]。它适用于我的场景。