Autor Beitrag
norman2306
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 222
Erhaltene Danke: 16

Win XP, Win 7 64-Bit
C# 4.0 (VS2010)
BeitragVerfasst: Di 23.03.10 11:15 
Servus!

Ich versuche seit knapp einer Stunde, ein Objekt mit Hilfe des BinSerializers zu serialisieren und es will einfach nicht klappen. Mir gehen langsam die Ideen aus, woran es liegen kann. Ich habe schon des öfteren serialisiert und bisher nie ein Problem gehabt. Die Serialisiertung wird durchlaufen. Aber wenn ich wieder deserialisiere, sind die Array Objekte in den Arrays null (siehe Kommentare im Code).

Das ist die Klasse (gekürzt), die serialisiert werden soll:
ausblenden volle Höhe C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
    [Serializable()]
    [PropGridAttr]
    [TypeConverterAttribute(typeof(VDTPropertyConverter))]
    [EditorAttribute()]//dynamicly set by the editor tool
    public class TInfo : Collection<TPoint>, iGPath, ISerializable
    {
        private string _tName;
        private string _identity;
        private GPath _path;
        private FPLCollection _timetables;

        #region ISerializable

        public void GetObjectData(SerializationInfo Info, StreamingContext Context)
        {
            
            Info.AddValue("TPs"this.ToArray());
            Info.AddValue("TT", _timetables.ToArray());
            Info.AddValue("N", _tName);
            Info.AddValue("ID", _identity);
        }

        protected TrackInfo(SerializationInfo Info, StreamingContext Context)
        {
            this._identity = Info.GetString("ID");
            this._tName = Info.GetString("N");
            this._timetables = new FPLCollection();
            this._timetables.Parent = this;
            TPoint[] tps = (TPoint[])Info.GetValue("TPs"typeof(TPoint[]));

//Dieses Array wird korrekt deserialisiert          
            foreach(TrackPoint TP in tps)
            {

                if (TP != null)
                {
                    this.Add(TP);
                }

            }

            FPL[] fpls = (Fahrplan[])Info.GetValue("TimeTables"typeof(Fahrplan[])); 

//Dieses Array hat zwar die richtige Länge, aber die Elemente sind null
            foreach (Fahrplan f in fpls)
            {
                if(f != null)
                _timetables.Add(f);
            }

            SetGPath();
        }
    }


Das sind die anderen Klassen:

ausblenden volle Höhe C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
    [Serializable()]
    public class TPoint
    {
        #region private variables
        private double _Mila;
        private double _Rvelo;
        private double _ss;
        private Int16 _Rad;
        private POIType _POI;
        private string _POIName;
        private double _lt;
        private double _lg;
        #endregion

    }

    [Serializable()]
    public class FPLPoint : TPoint
    {
        DateTime _arr;
        DateTime _dep;
        bool _pass;
        int _posID;
        FPLOptimize _simFlag;
    }


    [Serializable()]
    public class FPL : KeyedCollection<string, FPLPoint>, IBindingList, ISerializable
    {
        #region private variables
        private string _name;
        private string _ident = "";
        private bool _org;
        private FPLValidityFlags[] _validity = new FPLValidityFlags[0];
        private DateTime _validityStart;
        private DateTime _validityEnd;
        private DateTime[] _validityDates;
        private TrackInfo _parent;
        private FPLCollection _FPLCParent;

        #endregion


        #region ISerializable

        public void GetObjectData(SerializationInfo Info, StreamingContext Context)
        {
            Info.AddValue("FPL",this.ToArray());
            Info.AddValue("N", _name);
            Info.AddValue("I", _ident);
            Info.AddValue("V", _validity);
            Info.AddValue("S", _validityStart);
            Info.AddValue("E", _validityEnd);
            Info.AddValue("D", _validityDates);
        }

        protected FPL(SerializationInfo Info, StreamingContext Context)
        {
                FPLPoint[] Imp = (FPLPoint[])Info.GetValue("FPL",
                    typeof(FPLPoint[]));

                foreach (FPLPoint p in Imp)
                {
                    this.Add(p);
                }

                _name = Info.GetString("N");
                _ident = Info.GetString("I");
                _validity = (FPLValidityFlags[])Info.GetValue("V"typeof(FPLValidityFlags[]));
                _validityStart = Info.GetDateTime("S");
                _validityEnd = Info.GetDateTime("E");
                _validityDates = (DateTime[])Info.GetValue("D"typeof(DateTime[]));

        }

        #endregion
     }

    [Serializable()]
    [PropGridAttr]
    [TypeConverterAttribute(typeof(VDTPropertyConverter))]
    public class FPLCollection : KeyedCollection<string, Fahrplan>, ISerializable, IBindingList
    {
         #region ISerializable

        public void GetObjectData(SerializationInfo Info, StreamingContext Context)
        {
            FPL[] fpls = this.ToArray();
            Info.AddValue("F", fpls);     
        }

        protected FPLCollection(SerializationInfo Info, StreamingContext Context)
        {
                FPL[] imp = (Fahrplan[])Info.GetValue("F"typeof(FPL[]));
                for (int i = 0; i < imp.Length; i++)
                {
                    
                    if (imp[i] == null)
                    {
                        imp[i]= new FPL();
                        imp[i].Identification = String.Format("new FPL({0})", i);
                    }
                    imp[i].Parent = this._Parent;
                    imp[i].FPLCParent = this;
                    this.Add(imp[i]);

                }
        }

        #endregion
Kha
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Di 23.03.10 12:04 
ausblenden C#-Quelltext
1:
Info.AddValue("TT", ...					

ausblenden C#-Quelltext
1:
Info.GetValue("TimeTables", ...					

:nixweiss: ?
/edit: Das ist wohl nicht der originale Code, wenn die Array-Länge stimmt.

PS: Von Collections abzuleiten ist imo eher untypisch. Wenn du stattdessen eine Komposition wählst, sollten sich die Klassen doch auch ohne ISerializable serialisieren lassen, oder?

_________________
>λ=
norman2306 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 222
Erhaltene Danke: 16

Win XP, Win 7 64-Bit
C# 4.0 (VS2010)
BeitragVerfasst: Di 23.03.10 14:47 
@Kha

Du hast recht, ist nicht der orginale Code. Ich habe den Konstruktor etwas gekürzt, um nicht die ganzen nebensächlichen Funtkionsaufrufe drin zu haben. Der Übersichtlichkeit wegen. Die Zeile hatte ich versehentlich mitgelöscht und händisch (falsch) nachgetragen :) gutes Auge...

Die Klassen enthalten noch ziemlich viel Kram, der nicht serialisiert werden muss/soll. Deshalb ist ISerializable implementiert. Das ganze ist Teil eines Simulationstools und die Klassen bestanden schon. Ich bin jetzt für einige Erweiterungen zuständig (z.B. ein Tool zum Konfigurieren, einlesen etc.).

Ich gehe mal davon aus, dass die Collection verwendet wurde, um die ganzen Member (Add, Remove, IEnumerable-Impl. etc) ohne explizite Implementierung nutzen zu können(?). Bei einer Komposition müsste man das selbst reinbringen, was arbeitet bedeutet :). Außerdem weiß ich nicht, ob die Untereinheiten außerhalb nutzbar sein müssen. Da muss ich erst abklären. Dann könnte ich ja eine Komposition daraus machen.

Das Problem scheint daran zu liegen, das FPL selbst wieder ISerializable implementiert und der BinSerializer da nicht iterativ durch geht. Beim Debuggen ist mir aufgefallen, dass der IS-Konstruktor für FPL zwar aufgerufen wird, aber erst nach dem der Konstruktor für das übergeordnete TInfo schon durchgelaufen ist. Die Daten stehen also auch in dem Stream drin, sie werden nur "zu spät" deserialisiert und wer weiß wo hingeschrieben.

Aber erstmal vielen Dank für die Antwort
norman2306 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 222
Erhaltene Danke: 16

Win XP, Win 7 64-Bit
C# 4.0 (VS2010)
BeitragVerfasst: Di 23.03.10 17:13 
Das Problem liegt wohl bei der KeyedCollection. Irgendwie serialisiert er die nicht richtig.

Ich habe jetzt einen Wrapper geschrieben, als kleinen WorkAround. Nicht schön, aber funktioniert.