Can't use Interop objects in shared objects in .NET 4.0?

I work in VS 2010 and am working on updating our application to .NET 4. The application is built using Excel as a base, and we want to take advantage of some .NET improvements for using Excel. But I came across a strange error, which, apparently, was caused by using the Excel Interop object in the general dictionary. Here is the error that occurred:

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 is the actual property that has the problem:

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

Can't I use Interop objects in shared objects? If so, this is a serious limitation in .NET 4.0. I tried to set the Embed Interop property to false, but that didn't change anything. Please let me know if it is anyway.

Hooray!

Eric

+4
source share
3 answers

The new feature of VS2010 is to embed interaction types in an assembly, rather than using external interop assemblies.

The advantage is that you do not need to distribute interop assemblies.

The disadvantage is that each assembly gets its own set of interaction types.

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

You get a similar error if you make

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

I did not use VS2010, but I am sure that somewhere there is an option where you can disable the built-in interaction types.

+3
source

Adrian gave an almost correct answer, but there is a better way to deal with this error. Do not turn off the built-in interaction types, but use the common interface instead:

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

CLR 4.0 introduced the concept of type equivalence. If we simplified this a bit, we could say that CLR 4.0 treats two identically named interface types with identical Guid attributes as if they were the same type. The notion that type equivalence is very deeply embedded in the system and does work with equivalent types as if it were a single type. A few examples; 1. You can use reflection to invoke an interface method on an object that implements an equivalent interface. 2. Instances of common interfaces parameterized on equivalent interfaces are also considered equivalent.

C # and VB compilers use this function to implement the Insert Interrupt Types function.

Now to the exceptions: 1. Comparative comparisons between equivalent System.Type interfaces will fail, because there are still two different types in the type system:

 typeOfWorkbookFromAssemblyA.Equals(typeOfWorkbookFromAssemblyB) == false 

but there is a new Type.IsEquivalentTo API

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

Hope this helps.

+9
source

I got into a similar problem with Outlook AddIn, and the answer that Misha gives works like a charm. I had a property

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

and just changing List to IList interface solved the problem

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

All Articles