类型互操作不能嵌入。应该使用适用的接口。但“嵌入类型互操作”已经是假的。

4
在我的当前VSIX项目中,我遇到了以下错误:
Interop type 'ProjectKinds' cannot be embedded. Use the applicable interface instead

自然地,我谷歌了一下,几乎所有的SO答案都建议去项目引用中设置“嵌入互操作类型”为false - 在我的情况下是envDTE80。但是我已经检查过了,它并没有解决问题。
我还检查了“类似”的引用(EnvDTE、EnvDTE100和EnvDTE90),它们都将其“嵌入互操作类型”设置为false。
我正在尝试的代码是:
private static string test = ProjectKinds.vsProjectKindSolutionFolder;

编辑 #1:我还检查了.csproj文件,并确认该属性为false。
<Reference Include="EnvDTE80, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
  <EmbedInteropTypes>False</EmbedInteropTypes>
</Reference>

编辑 #2:微软本身似乎建议采用一种相当...hacky的解决方案作为最后的手段。对我来说看起来不太干净,但归根结底它能够运作。

https://blogs.msdn.microsoft.com/mshneer/2009/12/07/vs-2010-compiler-error-interop-type-xxx-cannot-be-embedded-use-the-applicable-interface-instead/


你能回答这个问题吗?微软解决方案的链接已经失效了。 - Vijay Nirmal
1个回答

4

如果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);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接