2010-10-09 8 views
3

Je suis actuellement complètement déconcerté par le problème que j'ai. J'écris un plug-in pour une autre application qui fournit une API .NET publique. J'ai créé une classe nommée Room et j'utilise un PropertyGrid pour permettre aux utilisateurs de voir et de modifier les propriétés des instances Room. Quelques propriétés sont limitées à un ensemble de valeurs standard. Ainsi, j'utilise des TypeDescripteurs personnalisés avec des substitutions GetStandardValues() pour que la grille de propriété affiche une liste déroulante pour ces propriétés.Objet InvalidCastException de coulée à son propre type

Tout fonctionnait très bien. Je recevais des listes déroulantes, et je pouvais éditer des valeurs sans problème. Pourtant maintenant pour une raison quelconque quand je choisis un Room le PropertyGrid montre les propriétés avec les descripteurs de type comme boîte noire.

alt text

Si je clique sur la boîte, il devient blanc et je reçois un curseur clignotant, mais je ne peux pas saisir quoi que ce soit. Si je puis sélectionner une autre chambre mon programme se bloque à l'exception suivante:

System.InvalidCastException was caught 
    Message=Unable to cast object of type 'DVAMC.Room' to type 'DVAMC.Room'. 
    Source=DVAMC 
    StackTrace: 
     at DVAMC.BuildingTypeConverter.GetStandardValuesSupported(ITypeDescriptorContext context) in C:\Documents and Settings\eric.anastas\My Documents\_SVN WC\DVAMC Working\BuildingTypeConverter.cs:line 14 
     at System.Windows.Forms.PropertyGridInternal.GridEntry.get_Flags() 
     at System.Windows.Forms.PropertyGridInternal.GridEntry.get_NeedsDropDownButton() 
     at System.Windows.Forms.PropertyGridInternal.PropertyDescriptorGridEntry.get_NeedsDropDownButton() 
     at System.Windows.Forms.PropertyGridInternal.PropertyGridView.SelectRow(Int32 row) 
     at System.Windows.Forms.PropertyGridInternal.PropertyGridView.SelectGridEntry(GridEntry gridEntry, Boolean fPageIn) 
     at System.Windows.Forms.PropertyGridInternal.PropertyGridView.GridPositionData.Restore(PropertyGridView gridView) 
     at System.Windows.Forms.PropertyGridInternal.PropertyGridView.Refresh(Boolean fullRefresh, Int32 rowStart, Int32 rowEnd) 
     at System.Windows.Forms.PropertyGridInternal.PropertyGridView.Refresh() 
     at System.Windows.Forms.PropertyGrid.Refresh(Boolean clearCached) 
     at System.Windows.Forms.PropertyGrid.set_SelectedObjects(Object[] value) 
     at System.Windows.Forms.PropertyGrid.set_SelectedObject(Object value) 
     at DVAMC.RoomDetailsForm.set_RoomDetailsSelectedRoom(Room value) in C:\Documents and Settings\eric.anastas\My Documents\_SVN WC\DVAMC Working\RoomDetailsForm.cs:line 115 
     at DVAMC.RoomDetailsForm.roomListTreeView_SelectionChanged(Object sender, EventArgs e) in C:\Documents and Settings\eric.anastas\My Documents\_SVN WC\DVAMC Working\RoomDetailsForm.cs:line 159 
     at BrightIdeasSoftware.ObjectListView.OnSelectionChanged(EventArgs e) 
     at BrightIdeasSoftware.ObjectListView.HandleApplicationIdle(Object sender, EventArgs e) 
     at System.Windows.Forms.Application.ThreadContext.System.Windows.Forms.UnsafeNativeMethods.IMsoComponent.FDoIdle(Int32 grfidlef) 
     at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData) 
     at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context) 
     at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context) 
     at System.Windows.Forms.Application.RunDialog(Form form) 
     at System.Windows.Forms.Form.ShowDialog(IWin32Window owner) 
     at System.Windows.Forms.Form.ShowDialog() 
     at DVAMC.RoomDetailsCmd.Execute(ExternalCommandData commandData, String& message, ElementSet elements) in C:\Documents and Settings\eric.anastas\My Documents\_SVN WC\DVAMC Working\RoomDetailsCmd.cs:line 44 
    InnerException: 

Le dernier élément dans les points de trace de pile à ma méthode BuildingTypeConverter.GetStandardValuesSupported() qui est ci-dessous.

GetStandardValuesSupported(System.ComponentModel.ITypeDescriptorContext context) 
{ 
    Room r = (Room)context.Instance; //this is line 14 referenced by the InvalidCastException's stack trace 

    if (r.IsLinked) 
    { 
     return true; 
    } 
    else 
    { 
     return false; 
    } 
} 

Maintenant, si je mets un point d'arrêt à la ligne 14 ci-dessus et essayer de déboguer le débogueur ne rompt pas au point d'arrêt. De plus, si j'ajoute du code arbitraire avant le cast, la trace de la pile de l'InvalidCastException semble toujours faire référence à la première ligne de GetStandardValues ​​(), quelle que soit sa nature. Par exemple, j'ai essayé ce qui suit.

public override bool GetStandardValuesSupported(System.ComponentModel.ITypeDescriptorContext context) 
    { 
     string s = "hello world"; //FIRST LINE 
     int i = 0; 


     Room r = (Room)context.Instance; 

     ..... 

J'ai toujours la même InvalidCastException. Pourtant, c'est la trace de pile référence la première ligne ci-dessus où j'initialise string s. De plus, si j'essayais de définir un point d'arrêt sur cette première ligne, il n'était pas non plus déclenché.

Comme je l'ai déjà dit auparavant était fonctionnait bien il ya un jour ou deux. J'ai même essayé de revenir aux révisions précédentes dans mon dépôt SVN. Je suis allé aussi loin que la première révision où j'ai créé la classe descripteur de type personnalisé, mais toujours rencontrer le problème avec le InvalidCastExceptions. Est-ce que quelqu'un a une idée de ce qui se passe?

+0

J'ai été récemment déconcerté d'une manière similaire et il s'est avéré être lié à code généré par le concepteur qui s'est levé lorsque j'ai nommé une propriété quelque chose qui a affronté –

+0

Humm intéressant. Pourtant, avec moi, cela ne fonctionne toujours pas, même si je reviens (y compris le code du concepteur) à une version qui fonctionnait. J'ai quelques propriétés avec le même nom que mes classes cependant. –

Répondre

1

Si la trace de la pile affiche toujours la même ligne même après que vous avez modifié le code qui indiquerait à moi que ProperyGrid n'exécute pas la même version de l'assembly. Ceci est encore confirmé lorsque vous dites que vous mettez un point d'arrêt mais que le point d'arrêt n'est jamais atteint. Si vous exécutez à l'intérieur du débogueur pour Visual Studio, je vous suggère de regarder la fenêtre de sortie (Ctrl + W, O), qui liste tous les assemblys (avec leur chemin) qui sont chargés dans l'exécution. J'ai vu la confusion de la version d'assemblage en particulier lorsque l'assembly est dans le GAC, où il insiste pour charger une ancienne version de l'assembly.

+1

Oui, je ne sais pas pourquoi, mais il y avait une copie séparée de mon fichier DLL dans le dossier du programme racine. Ce qui est bizarre, c'est que mon code semble référencer les deux. Par exemple, je pourrais attraper un point d'arrêt dans le gestionnaire d'événements SelectionChanged, mais après avoir défini la propriété PropertyGrid.SelectedObject à cet emplacement, il n'attraperait pas de point d'arrêt dans la méthode GetStandardValues ​​(). J'ai supprimé la copie supplémentaire de la DLL et cela a fonctionné parfaitement encore. Merci! –

+0

+1 vous venez de me sauver un moment important mon ami! – Achilles

0

Il se peut que les deux types soient réellement différents - par exemple si l'un d'entre eux est chargé à partir d'une autre version d'un assemblage que l'autre. Je ne sais pas si cela pourrait arriver dans votre cas, mais cela pourrait poser problème.

La méthode la plus simple pour vérifier cela consiste à placer le point d'arrêt à l'endroit où l'exception est levée. Ensuite, vous pouvez regarder les deux types dans les montres ou la fenêtre immédiate et regarder o1.GetType().Assembly. FullName (et de même pour l'autre objet).