两个程序集中定义了相同的类型

4

我有一个使用CustomTaskPanes的VSTO插件,代码可以编译并正常工作,但问题出现在Resharper和Code contracts for .net等代码分析器中。

这段代码会导致这两个分析器都产生错误消息:

CustomTaskPane taskPane = CustomTaskPanes.Add(new UserControl(), "Title");
taskPane.DockPosition = MsoCTPDockPosition.msoCTPDockPositionFloating;

无法将源类型'Microsoft.Office.Core.MsoCTPDockPosition [office,版本=15.0.0.0,文化=中性,公钥标记=71e9bce111e9429c]'转换为目标类型'Microsoft.Office.Core.MsoCTPDockPosition [Microsoft.Office.Tools.Common,版本=10.0.0.0,文化=中性,公钥标记=b03f5f7f11d50a3a]'
这很奇怪,因为公共类型Microsoft.Office.Core.MsoCTPDockPosition仅存在于office.dll中。无论如何,我尝试使用别名解决它,并将Microsoft.Office.Tools.Common命名为Tools_Common:
extern alias Tools_Common;
using System;
using System.Windows.Forms;
using Microsoft.Office.Core;
using Tools_Common::Microsoft.Office.Tools;
using CustomTaskPane = Tools_Common::Microsoft.Office.Tools.CustomTaskPane;

但是它并没有起到任何帮助作用。这个问题的原因是什么?我该如何解决它(特别是针对代码合同)?
此外,我发现另一个奇怪的现象——Resharper的自动补全显示MsoCTPDockPosition好像存在于Microsoft.Office.Tools.Common.dll中,但当我尝试进行自动补全时,它使用了office.dll版本: enter image description here

它们都有用。但我不能杀掉它们中的任何一个,因为我正在使用它们。而且说实话,我需要杀掉它们才能让代码分析器满意吗?这是一件很常见的事情,这就是别名被发明的原因,但在这里它没有帮助。即使没有别名,编译器也可以正常工作。 - Alex Butenko
就像我一样,不要使用Resharper!哈哈这听起来像是Resharper或Code Contracts中的一个错误。其中一个实际上正在尝试加载类型,并且它抓取的与第一个引用的dll中的类型冲突,或者类似于这些行。老实说,我都不使用这些工具,我发现Visual Studio 2015已经足够好了,我不再需要Resharper。 - Ryan Mann
从来没有与合同打过交道,所以无法说。 - T.S.
@CindyMeister 对不起,我不知道什么是Office.Taskpane以及如何获取.InnerObject。我很乐意学习。 - Alex Butenko
VSTO对象始终派生自本机Office对象。 VSTO对象位于“Tools”命名空间中; 本机Office对象位于“Interop”命名空间中。 现在,您正在使用Tools.Taskpane,但它是基于Office.Taskpane构建的。 每个从Interop对象派生的VSTO对象都具有InnerObject属性。 只需键入“。”,您就可以在Intellisense中获得它。 InnerObject访问“包装在”VSTO对象中的本机对象。 试试看吧 :-)? - Cindy Meister
显示剩余4条评论
2个回答

2
你应该在VS的COM选项卡中使用Microsoft Office 15.0 Object Library,而不是office.dll。

0

所以,我尝试了几种不同的方法并找到了解决方案。我发现,如果我将Office.dll程序集从

C:\Program Files (x86)\Microsoft Visual Studio 14.0\Visual Studio Tools for Office\PIA\Office15\Office.dll, 15.0.4420.1017

更改为

C:\Windows\assembly\GAC_MSIL\office, 15.0.4787.1001

那么Resharper就可以正常工作了。但是Code Contracts仍然给我相同的错误。所以我使用了dynamic关键字来欺骗它。

((dynamic) taskPane).DockPosition = MsoCTPDockPosition.msoCTPDockPositionFloating;

我对使用 dynamic 并不是很满意。但代码契约对我来说非常重要,所以我可以容忍一点肮脏的代码。

如果有人能解释一下,为什么我更改了版本后 Resharper 开始工作良好,或者能够找到更好、更干净的代码契约解决方案,我会重新接受答案。

编辑:

((dynamic) taskPane).DockPosition 显示 TargetExceptions 并且说该属性在对象中不存在。因此我将其更改为使用反射。

typeof(CustomTaskPane)
    .InvokeMember("DockPosition", BindingFlags.SetProperty, null, taskPane, new object[] { MsoCTPDockPosition.msoCTPDockPositionFloating }, null);

1
说实话,我浪费了很多时间去完成同样的练习。我有一个大型的钢铁项目,里面有很多这些错误。最后,我只是手动设置每个错误被忽略,并使用R#继续我的生活,这很烦人,但至少完成了工作。我很想知道一个真正的解决方案。你上面提到的替换方法不起作用。动态技巧确实有效。我也尝试过进行显式转换,这使编译器满意,但R#不满意。 - Wade Hatler

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