2009-11-19 3 views
4

Je travaille dans VS 2010 et travaille sur la mise à niveau de notre application vers .NET 4. L'application est construite avec Excel comme base et nous voulons profiter des améliorations apportées à .NET pour utiliser Excel. Mais j'ai rencontré une erreur étrange qui semble être causée par l'utilisation d'un objet Excel Interop dans un dictionnaire générique. Voici l'erreur qui a été généré:Sommes-nous incapables d'utiliser des objets Interop dans des objets génériques dans .NET 4.0?

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. 

Voici la propriété réelle qui a la question:

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

Sommes-nous incapables d'utiliser des objets Interop dans les objets génériques? Si c'est le cas, il s'agit d'une limitation sérieuse dans .NET 4.0. J'ai essayé de définir la propriété Embed Interop sur false, mais cela ne semblait pas changer quoi que ce soit. S'il vous plaît laissez-moi savoir s'il y a de toute façon autour de cela.

À la votre!

Erick

Répondre

3

Une nouvelle fonctionnalité de VS2010 est d'intégrer les types de PIA dans l'ensemble au lieu d'utiliser des ensembles Interop externes.

L'avantage est que vous n'avez pas besoin de distribuer les assemblages interopérables. L'inconvénient est que chaque assemblage possède son propre ensemble de types d'interopérabilité.

Depuis le type « Excel.Worksheet » est maintenant interne à votre assemblée, d'autres ensembles ne peuvent pas utiliser un type générique basé sur (ce qui est ce que le message d'erreur indique)

vous obtenez une erreur similaire si vous

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

Je ne l'ai pas utilisé VS2010 mais je suis sûr qu'il doit y avoir une option quelque part où vous pouvez désactiver les types de PIA embarqués.

+0

Adrian, C'est ce que j'ai compris donc merci pour la confirmation. J'ai fini par devoir désactiver l'intégration dans toute la solution. Je suis à la recherche d'un moyen de contourner mais je n'ai pas eu le temps d'expérimenter. Peut-être une sorte d'interface? Faites-moi savoir vos pensées à ce sujet. Merci! – Erick

+0

La seule autre façon de contourner cela est de créer une sorte d'affinité d'assemblage (comme le modèle de thread STA). Vous pouvez faire circuler les objets interop, en les convertissant en objet, mais dès que vous avez besoin d'y accéder, vous devez effectuer l'appel depuis l'assemblage où ils ont été créés. D'un autre côté, qu'est-ce qui ne va pas avec l'utilisation d'assemblages interop pour le bureau? Ils seront sur la machine des utilisateurs de toute façon puisqu'ils font partie d'une installation normale. Vous n'obtiendrez rien de l'interopérabilité intégrée. – adrianm

+0

correct. l'intégration n'est pas si merveilleuse. Pour utiliser Interops, les utilisateurs doivent disposer d'une copie sous licence d'Office. La plupart auront Office 2007 qui vient avec le PIA pré-installé ....: D –

9

Adrian a donné presque une réponse correcte, mais il y a une meilleure façon de traiter cette erreur. Ne pas éteindre Intégrer Interop types, mais utiliser une interface générique à la place:

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

CLR 4.0 introduit un concept de type Equivalence. Si nous devions simplifier légèrement ce que cela signifie alors nous pourrions dire que CLR 4.0 traite deux types d'interface nommés de manière identique, avec des attributs Guid identiques comme s'il s'agissait du même type. Notices que l'équivalence de type est construit très profondément dans le système et fait travailler avec des types équivalents comme si c'était un type. Quelques exemples 1. Vous pouvez utiliser la réflexion pour appeler une méthode d'interface sur un objet implémentant une interface équivalente. 2. Les instances des interfaces génériques paramétrées sur des interfaces équivalentes sont également considérées comme équivalentes.

Les compilateurs C# et VB tirent parti de cette fonctionnalité pour implémenter la fonction "Embed Interop Types".

maintenant des exceptions: 1. Les comparaisons de référence entre les interfaces équivalentes System.Type de échouera puisque ceux-ci sont encore deux types différents dans le système de type:

typeOfWorkbookFromAssemblyA.Equals(typeOfWorkbookFromAssemblyB) == false 

mais il y a un nouveau type d'API.IsEquivalentTo

typeOfWorkbookFromA.IsEquivalentTo(typeOfWorkbookFromB) == true 
  1. Deux instances de la même classe générique paramétrés sur les interfaces équivalentes ne sont pas considérés comme équivalents.

Espérons que cela aide.

+0

Merci beaucoup pour ce conseil et cela a fonctionné! Je t'en ai donné un! – Pascal

1

Je suis entré dans le même problème avec Outlook AddIn et la réponse fournie par Misha fonctionne comme un charme. j'avais une propriété

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

et simple changement de List à l'interface IList a résolu le problème

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