互操作类型无法嵌入。请改用适用的接口。但是“嵌入式互操作类型”已经为假

时间:2018-08-28 09:00:21

标签: c# visual-studio visual-studio-2017 vsix

在当前的VSIX项目中,出现以下错误:

Interop type 'ProjectKinds' cannot be embedded. Use the applicable interface instead

自然,我用Google搜索了它,几乎所有SO answers都建议转到“项目参考”(在我的情况下为envDTE80),并将“嵌入互操作类型”设置为false。但是我已经检查过了,它不能解决问题。

我还检查了“相似”引用(EnvDTE,EnvDTE100和EnvDTE90),它们的“嵌入互操作类型”都设置为false。

我要执行的代码是:

private static string test = ProjectKinds.vsProjectKindSolutionFolder;

编辑#1:我还检查了.csproj并确认该属性为假

<Reference Include="EnvDTE80, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
  <EmbedInteropTypes>False</EmbedInteropTypes>
</Reference>

编辑#2:Microsoft自己似乎提出了一种.. 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/

1 个答案:

答案 0 :(得分:0)

Microsoft Blog Post,以防EDIT#2中的链接再次断开。

致谢博客文章作者Misha Shneerson。

一些用户报告说,当使用Visual Studio 2010并引用“嵌入的互操作类型”设置为TRUE的互操作程序集时,他们会从字面上得知该类型无法嵌入的错误。然后,该错误将建议您使用接口-但没有许多其他详细信息,可从何处获得此接口。这篇文章旨在解释该错误,并为该接口提供简单指导。

“嵌入互操作类型”功能的局限性之一是嵌入程序集时不能使用类。此限制与服务有关-嵌入元数据是安全的,但不能嵌入可能包含可执行代码的任何内容(类类型包含元数据和代码,而接口仅包含元数据)。当您尝试从“嵌入的互操作类型”设置为TRUE的互操作程序集引用类类型时,请发出警告。但是在大多数情况下,您不需要使用互操作程序集中的类,并且只需进行少量代码调整即可成功使用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类设为“ internal”,将其重命名为EnvDTEConstants。

internal abstract class EnvDTEConstants
{
    public const string vsDocumentKindText = "{8E7B96A8-E33D-11D0-A6D5-00C04FB67F6A}";
}

接下来,我将遍历我的代码并将所有出现的EnvDTE.Constants更改为EnvDTEConstants。现在我的代码可以编译了!

System.Windows.Forms.MessageBox.Show(EnvDTEConstants.vsDocumentKindText);