如果EDIT #2中的链接再次失效,可以查看微软博客文章。
感谢博客文章的作者Misha Shneerson。
一些用户报告说,在使用Visual Studio 2010并引用设置为“嵌入互操作类型”的Interop程序集时,会出现错误提示,字面意思是该类型无法嵌入。然后该错误会建议使用接口-但没有提供关于在哪里获取此接口的详细信息。本文旨在解释这个错误,并给出一个简单的指南,说明接口是什么。
“嵌入互操作类型”功能的局限之一是,当嵌入程序集时,不能使用类。这种限制与服务有关-嵌入元数据是安全的,但不能嵌入可能包含可执行代码的任何内容(类类型包含元数据和代码,而接口只包含元数据)。 当您尝试从“Embed Interop Types”设置为TRUE的Interop程序集中引用类类型时,编译器会发出警告。但是,在大多数情况下,您不需要使用Interop程序集中的类,并且需要进行少量代码调整以成功编译EIT = true。
让我们首先解决此错误的最常见情况。我还将介绍用户代码使用VSIP程序集 EnvDTE.Constants / VSLangProj.PrjKind 中的常量的情况...
在大多数情况下(例如在评论中指出的使用UPnPNATClass时的错误),此错误是尝试实例化COM对象的代码导致的,例如以下代码片段启动Excel:
Excel.ApplicationClass xlapp = new Excel.ApplicationClass();
在这里,只需要说Excel.ApplicationClass源自Excel.Application接口,甚至可以使用Excel.Application接口来实例化Excel。 将此代码重写为以下内容可以生成完全相同的结果:
Excel.Application xlapp = new Excel.Application();
通常情况下,将代码修改为使用接口类型而不是类类型,只需删除“Class”后缀并编译代码即可!另一种查找适用接口的方法是查看类类型的定义。该类通常从一个或多个接口派生。查看每个接口的定义 - 其中一个将具有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}";
}
然后我会将Constants类设置为“内部”,并将类重命名为EnvDTEConstants。
internal abstract class EnvDTEConstants
{
public const string vsDocumentKindText = "{8E7B96A8-E33D-11D0-A6D5-00C04FB67F6A}";
}
接下来,我将检查我的代码并将所有出现的EnvDTE.Constants更改为EnvDTEConstants。现在我的代码可以编译了!
System.Windows.Forms.MessageBox.Show(EnvDTEConstants.vsDocumentKindText);