Microsoft 博客帖子以防 EDIT #2 中的链接再次断开。
感谢博文作者 Misha Shneerson。
一些用户报告说,当使用 Visual Studio 2010 并在“嵌入互操作类型”设置为 TRUE 的情况下引用互操作程序集时,他们会收到错误消息,即无法嵌入该类型。然后错误会建议使用接口 - 但没有关于从何处获取此接口的其他详细信息。这篇文章旨在解释错误并就界面是什么提供简单的指导。
“嵌入互操作类型”功能的限制之一是嵌入程序集时无法使用类。此限制与服务有关 - 嵌入元数据是安全的,但不是任何可能包含可执行代码的东西(类类型包含元数据和代码,而接口仅包含元数据)。当您尝试从“嵌入互操作类型”设置为 TRUE 的互操作程序集中引用类类型时,编译器会发出警告。但在大多数情况下,您不需要使用互操作程序集中的类,并且需要对代码进行少量调整才能使用 EIT=true 成功编译。
让我们首先解决此错误的最常见情况。我还将解决用户代码使用来自 VSIP 程序集的常量的情况,例如下面的 EnvDTE.Constants / VSLangProj.PrjKind...
在大多数情况下(例如在其中一个 cmets 中指出的使用 UPnPNATClass 的错误),此错误是尝试实例化 COM 对象的代码的结果,例如这里是启动 Excel 的一段代码:
Excel.ApplicationClass xlapp = new Excel.ApplicationClass();
这里可以说 Excel.ApplicationClass 派生自 Excel.Application 接口,甚至可以使用 Excel.Application 接口来实例化 Excel。如下重写此代码会产生完全相同的结果:
Excel.Application xlapp = new Excel.Application();
通常,要将代码更改为使用接口类型而不是类类型,您只需删除“类”后缀并编译代码!另一种查找适用接口是什么的方法——查看类类型的定义。类通常派生自一个或多个接口。查看每个接口的定义 - 其中一个将具有 CoClass 属性,这就是您要查找的接口。
EnvDTE/VSLangProj 的情况有点不同。我相信应该有来自 VSIP 团队的建议,鼓励使用类型嵌入。不幸的是,EnvDTE/VSLangProj 程序集中的某些常量无法嵌入。对于这些,您需要手动将常量的值嵌入到您的项目中。因为这些是抽象类中的常量字段并且永远不应更改 - 这是一个安全的做法。
在 IDE 中,您可以右键单击需要嵌入的值,然后在本地复制和粘贴这些值。
例如,假设我的 C# 代码有这样的代码:
System.Windows.Forms.MessageBox.Show(EnvDTE.Constants.vsDocumentKindText);
编译这段代码时会出现编译错误:
<errors>
'EnvDTE.Constants' does not contain a definition for 'vsDocumentKindText'
Interop type 'EnvDTE.Constants' cannot be embedded. Use the applicable interface instead.
</errors>
在 IDE 中,我将右键单击 vsDocumentKindText 并选择“转到定义”。这将使我看起来像是常量类的定义。我将复制以下行并将其粘贴到我的代码中:
public abstract class Constants
{
public const string vsDocumentKindText = "{8E7B96A8-E33D-11D0-A6D5-00C04FB67F6A}";
}
然后我将常量类设为“内部”,将类重命名为 EnvDTEConstants。
internal abstract class EnvDTEConstants
{
public const string vsDocumentKindText = "{8E7B96A8-E33D-11D0-A6D5-00C04FB67F6A}";
}
接下来,我将检查我的代码并将所有出现的 EnvDTE.Constants 更改为 EnvDTEConstants。现在我的代码可以编译了!
System.Windows.Forms.MessageBox.Show(EnvDTEConstants.vsDocumentKindText);