我们是否无法在 .NET 4.0 中的通用对象中使用 Interop 对象?

发布于 2024-08-11 13:59:06 字数 710 浏览 6 评论 0原文

我正在 VS 2010 中工作,致力于将我们的应用程序升级到 .NET 4。该应用程序是以 Excel 为基础构建的,我们希望利用 .NET 的一些改进来使用 Excel。但我遇到了一个奇怪的错误,该错误似乎是由在通用字典中使用 Excel Interop 对象引起的。这是生成的错误:

C:\MyApp\TheAssembly\MyClass.cs(823,57): 
error CS1769: Type 'MyApp\OtherAssemply.IMyController.SheetReports' from assembly 'c:\MyApp\OtherAssemply.\bin\Debug\OtherAssembly.dll' 
 cannot be used across assembly boundaries because it has a generic type 
 parameter that is an embedded interop type.

这是存在问题的实际属性:

Dictionary<Excel.Worksheet, IReportSheet> SheetReports { get;}

我们无法在通用对象中使用 Interop 对象吗?如果是这样,这就是 .NET 4.0 中的一个严重限制。我尝试将 Embed Interop 属性设置为 false,但这似乎没有改变任何内容。请告诉我是否有任何解决办法。

I'm working in VS 2010 and working on upgrading our application to .NET 4. The application is built with Excel as the base and we want to take advantage of some of the improvements to .NET for using Excel. But I ran across a strange error that seems to be caused by using an Excel Interop object in a generic dictionary. Here is the error that was generated:

C:\MyApp\TheAssembly\MyClass.cs(823,57): 
error CS1769: Type 'MyApp\OtherAssemply.IMyController.SheetReports' from assembly 'c:\MyApp\OtherAssemply.\bin\Debug\OtherAssembly.dll' 
 cannot be used across assembly boundaries because it has a generic type 
 parameter that is an embedded interop type.

Here's the actual property that has the issue:

Dictionary<Excel.Worksheet, IReportSheet> SheetReports { get;}

Are we unable to use Interop objects in generic objects? If so, this is a serious limitation in .NET 4.0. I tried setting the Embed Interop property to false, but that didn't seem to change anything. Please let me know if there is any way around this.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

梦旅人picnic 2024-08-18 13:59:06

阿德里安给出了几乎正确的答案,但有更好的方法来处理这个错误。不要关闭嵌入互操作类型,而是使用通用接口:

IDictionary<Excel.Worksheet, IReportSheet> SheetReports { get;} 

CLR 4.0 引入了类型等效的概念。如果我们稍微简化一下这意味着什么,那么我们可以说 CLR 4.0 将两个具有相同命名的接口类型(具有相同的 Guid 属性)视为同一类型。请注意,类型等效性非常深入地构建在系统中,并且使得使用等效类型就好像它是一种类型一样。例子很少;
1. 您可以使用反射来调用实现等效接口的对象上的接口方法。
2. 在等效接口上参数化的通用接口实例也被认为是等效的。

C# 和 VB 编译器利用此功能来实现“嵌入互操作类型”功能。

现在来说说例外情况:
1. 等效接口 System.Type 之间的引用比较将失败,因为它们在类型系统中仍然是两种不同的类型:

typeOfWorkbookFromAssemblyA.Equals(typeOfWorkbookFromAssemblyB) == false

但有一个新的 API Type.IsEquivalentTo

typeOfWorkbookFromA.IsEquivalentTo(typeOfWorkbookFromB) == true
  1. 参数化的同一泛型 class 的两个实例等效接口不被视为等效。

希望这有帮助。

Adrian gave almost a correct answer but there is a better way of dealing with this error. Do not turn off Embed Interop Types but use a generic interface instead:

IDictionary<Excel.Worksheet, IReportSheet> SheetReports { get;} 

CLR 4.0 introduced a concept of Type Equivalence. If we were to slightly simplify what this means then we could say that CLR 4.0 treats two identically named interface types, with identical Guid attributes as if it is the same type. Notices that type equivalence is built very deeply into the system and makes working with equivalent types as if it was one type. Few examples;
1. You can use reflection to invoke an interface method on an object implementing an equivalent interface.
2. Instances of generic interfaces parameterized on equivalent interfaces are also considered to be equivalent.

C# and VB compilers take advantage of this feature to implememnt "Embed Interop Types" feature.

Now to the exceptions:
1. The reference comparisons between equivalent interfaces System.Type's will fail since these are still two different types in the type system:

typeOfWorkbookFromAssemblyA.Equals(typeOfWorkbookFromAssemblyB) == false

but there is a new API Type.IsEquivalentTo

typeOfWorkbookFromA.IsEquivalentTo(typeOfWorkbookFromB) == true
  1. Two instances of the same generic class parameterized on equivalent interfaces are not considered to be equivalent.

Hope this helps.

孤独岁月 2024-08-18 13:59:06

VS2010 的一个新功能是将互操作类型嵌入到程序集中,而不是使用外部互操作程序集。

好处是您不需要分发互操作程序集。

缺点是每个程序集都有自己的一组互操作类型。

由于类型“Excel.Worksheet”现在是您程序集的内部类型,因此其他程序集无法使用基于它的通用类型(这就是错误消息所说的内容)

如果您这样做,您会收到类似的错误

internal class X { }
public class Y {
    public List<X> l;
}

我没有使用过 VS2010,但是我确信一定有一个选项可以关闭嵌入式互操作类型。

A new feature of VS2010 is to embed the interop types into the assembly instead of using external interop assemblies.

The benefit is that you don't need to distribute the interop assemblies.

The drawback is that each assembly get its own set of the interop types.

Since the type "Excel.Worksheet" is now internal to your assembly, other assemblies can't use a generic type based on it (which is what the error message says)

You get a similar error if you do

internal class X { }
public class Y {
    public List<X> l;
}

I have not used VS2010 but I'm sure there must be an option somewhere where you can turn off the embedded interop types.

做个少女永远怀春 2024-08-18 13:59:06

我在 Outlook AddIn 中遇到了类似的问题,Misha 提供的答案非常有效。
我有一个属性

public List<Microsoft.Office.Interop.Outlook.Attachment> Attachments { get; set; }

,并将 List 简单更改为接口 IList 解决了问题

public IList<Microsoft.Office.Interop.Outlook.Attachment> Attachments { get; set; }

I got into the similar issue with Outlook AddIn and the answer provided by Misha works like a charm.
I had a property

public List<Microsoft.Office.Interop.Outlook.Attachment> Attachments { get; set; }

and simple change of List to interface IList solved the problem

public IList<Microsoft.Office.Interop.Outlook.Attachment> Attachments { get; set; }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文