Laden...

Das Objekt des Typs FOO kann nicht in Typ FOO umgewandelt werden?

Letzter Beitrag vor 16 Jahren 14 Posts 3.491 Views
Das Objekt des Typs FOO kann nicht in Typ FOO umgewandelt werden?

Hallo,

ich habe ein merkwürdiges Phänomen beim Deserialisieren eines Objekts:

BinaryFormatter formatter = new BinaryFormatter();
MemoryStream stream = new MemoryStream((byte[])viewRow["Settings"]);
object obj = formatter.Deserialize(stream);
_Settings = (ViewSettings)obj;

Die letzte Zeile wirft die Exception (Das Objekt des Typs ViewSettings kann nicht in Typ ViewSettings umgewandelt werden.

Betrachte ich mir im Debugger aber die Variable obj , dann enthält sie genau diesen Typ (ViewSettings).

Noch verschärfter:
Gebe ich die Anweisung

_Settings = (ViewSettings)obj;

im Überwachungsfenster ein, wirft dieses keinen Fehler und die Variable _Settings ist richtig belegt.
Was übersehe ich hier?
Was macht der ausgeführte Code anders als das Überwachungsfenster?

Thanx vorab
Ron

Riecht danach, dass du zwei Typen des Namens ViewSettings in zwei verschiedenen Namespaces hast.

Ich tippe auf Versionsghetto 🙂

Mit Version 1 serialisiert und mit Version 2 deserialisiert.

Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...

hi svenson,
stimmt, riecht voll danach, aber leider ist dem nicht so.

ich habe sogar schon per explorer-suche nach dem begriff ViewSettings im gesamten Entwicklungspfad gesucht; da ist definitiv nix doppelt deklariert.

hi hans
auch Dir danke, aber leider: nope.
datenzeile gelöscht, anwendung gestartet, in tabelle serialisiert, datensatz da, alles cool, dann deserialisiert, gleiches resultat.

hi alle anderen, 😉
gibt´s noch mehr ideen...?

Lass dir dochmal den FullQualifiedName des Typs des Objektes geben.

hi svenson,

objektvariable obj liefert beim debuggen als assembly und vollqualifizierten namen exakt das gleiche wie im überwachungsfenster die typdeklaration ViewSettings.

Alles stimmt haargenau überein, inkl. Assemblyversion.

Schliess mal die Entwicklungsumgebung und kille das Obj-Verzeichnis... ev. hilft es

Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...

Hallo citizen.ron,

ich gehe davon aus, dass die DLL, die ViewSettings definiert, zwischen Serialisieren und Deserialisieren neu übersetzt wurde. Ich denke, das reicht, damit ViewSettings nicht mehr als der gleiche Typ angesehen wird.

herbivore

danke herbivore,
aber das ist definitiv nicht so.

ich habe es nach deinem post explizit nochmals probiert:
datenzeile löschen, anwendung starten, anwendung beendet => serialisierung in tabellenzeile und -feld, anwendung erneut gestartet, deserialisierung schlägt fehl.

das objekt ist zwar ein bisschen komplexer, weil es dictionaries enthält, aber dennoch - die exception ist schlicht unerklärlich; im überwachungsfenster kann ich wie gesagt die zuweisung problemlos vornehmen - als codeanweisung kracht sie aber. außerdem hat es irgendwann mal funktioniert.

zur vertiefung hier noch das zu serialisiernde objekt (Ziel des ganzen ist, in der datenbank zu speichern, welche spaltenausblendungen, sortierungen, selektionen & markierungen etc. ein benutzer in einer beliebigen tabellenansicht vorgenommen hat):


using System;
using System.Collections.Generic;
using System.Text;
using CCL.Common;
using System.Windows.Forms;

namespace CAF.Views
{
   partial class View
   {
   // InformationCategorySetting
      /// <summary>
      /// Category dependant settings
      /// </summary>
      [Serializable()]
      public class InformationCategorySetting : IInformationCategorySetting
      {
      #region Property-bound members
         private Guid               _Selection;
         private Type               _SubviewType;
         private eRecordsetView     _RecordsetView;
         private List<Guid>         _HighlightedItems;
         private List<String>       _HiddenColumns;
         public SortedList<int, string> _GroupingColumns;

         [NonSerialized]
         private ContextMenuStrip   _ContextMenuStrip;
      #endregion

      #region Properties
         public Guid Selection
         {
            get { return _Selection; }
            set { _Selection = value; }
         }
         public Type SubviewType
         {
            get { return _SubviewType; }
            set { _SubviewType = value; }
         }
         public eRecordsetView RecordsetView
         {
            get { return _RecordsetView; }
            set { _RecordsetView = value; }
         }
         public List<Guid> HighlightedItems
         {
            get { return _HighlightedItems; }
            set { _HighlightedItems = value; }
         }
         public List<String> HiddenColumns
         {
            get { return _HiddenColumns; }
            set { _HiddenColumns = value; }
         }
         public SortedList<int, string> GroupingColumns
         {
            get { return _GroupingColumns; }
            set { _GroupingColumns = value; }
         }
         public ContextMenuStrip ContextMenuStrip 
         { 
            get { return _ContextMenuStrip; }
            set {_ContextMenuStrip = value; } 
         }
      #endregion

      #region .ctor
      // Plain constructor for deserialization
         public InformationCategorySetting() 
         {
            _GroupingColumns = new SortedList<int,string>();
            _HiddenColumns   = new List<String>();
            _HighlightedItems = new List<Guid>();
            _RecordsetView = eRecordsetView.DataGrid;
         }

      // Initialization constructor for use in application
         public InformationCategorySetting(Type type) : this()
         {
            _SubviewType = type;
            _Selection = Guid.Empty;
         }
      #endregion
      }

   // ViewSettings
      /// <summary>
      /// A class designed for XML Serialization storing user settings of a view
      /// </summary>
      [Serializable()]
      public class ViewSettings
      {
         #region Public members
            public string        SelectedCategory;
            public Dictionary<string, IInformationCategorySetting>  CategorySettings;
         #endregion

         #region .ctor
         // Plain constructor for deserialization
            public ViewSettings() 
            {
               SelectedCategory = string.Empty;
               CategorySettings = new Dictionary<string, IInformationCategorySetting>();
            }
         #endregion
      }

   #region Associated properties
      private Dictionary<string, eRecordsetView> _AvailableRecordsetContainers;
      public Dictionary<string, eRecordsetView> AvailableRecordsetContainers
      {
         get { return _AvailableRecordsetContainers; }
         set {_AvailableRecordsetContainers = value; }
      }
   #endregion
   }
}

Probier mal die Daten zu serialisieren und ohne die Anwendung zu beenden wieder zu deserialisieren.... falls dies funktioniert, dann liegt es definitiv an der Version des Assembly.

Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...

Hallo zusammen,

falls jemand mal in die gleiche Falle läuft, hier also heute die Lösung.

Man deklariere eine Schnittstelle IFoo für Foo und dann gehts 😉


protected internal void LoadSettings(DataRow viewRow)
{
// Read binary settings
   if (viewRow["Settings"] != DBNull.Value) try
   {
      BinaryFormatter formatter = new BinaryFormatter();
      MemoryStream stream = new MemoryStream((byte[])viewRow["Settings"]);
      object obj = formatter.Deserialize(stream);
      if (obj is IViewSettings)
         _Settings = (IViewSettings)obj;
   }
   catch {}
   if (_Settings == null)
      _Settings = new ViewSettings(); 
}

PS:
Ich weiß zwar immer noch nicht, woher der Fehler kommt, denn ohne Schnittstelle tritt er immer noch auf, aber so wird zur Laufzeit das Objekt wenigstens als IViewSettings erkannt.

hth
ron

Naja das ist ja nu keine Lösung, sondern nur ein Workaround. Aber wenn es mit Schnittstelle geht liegt es definitiv nicht an der Assemblyversion und die Deserialisierung an sich ist auch i.O....

Hallo citizen.ron

hast du es auch mal mit der Variante von Programmierhans versucht?

lg
LastGentleman

"Das Problem kennen ist wichtiger, als die Lösung zu finden, denn die genaue Darstellung des Problems führt automatisch zur richtigen Lösung." Albert Einstein

@LastGentleman
ja, klappt ebenfalls nicht.
direkt nach der serialisierung zu deserialisieren liefert im programmcode exakt den gleichen fehler, im überwachungsfenster aber keinen

ps:
ja, ich habe die aktuellsten servicepacks an allen fronten installiert 😉