Autor Beitrag
Schulteatq
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 16



BeitragVerfasst: Sa 09.06.12 09:51 
Moin zusammen,

bekanntermaßen ist aus unerfindlichen Gründen System.Drawing.Color nicht serialisierbar. Für den Fall, dass die Farbe doch serialisiert werden sollte, habe ich mir immer so geholfen:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
private Color _color;
public int argbColor
  {
  get { return _color.ToArgb(); }
  set { _color = Color.FromArgb(value); }
  }


Funktioniert super. Wenn ich das gleiche Verfahren jetzt jedoch auf eine List<Color> anwende, funktioniert die serialisierung hervorragend, bei der Deserialisierung wird jedoch leider nicht der set-accessor aufgerufen. Hier ein wenig Code:
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:
[Serializable]
public class ColorMap
  {
  /// <summary>
  /// List of all colors in this color map.
  /// </summary>
  private List<Color> _colors;

  /// <summary>
  /// List of all colors int this color map in ARGB format. When using set accessor, the colors will be overwritten.
  /// </summary>
  public List<int> _argbColors
    {
    get
      {
      List<int> l = new List<int>();
      if (_colors != null)
        foreach (Color c in _colors)
          l.Add(c.ToArgb());
      return l;
      }
    set
      {
      _colors = new List<Color>();
      foreach (int c in value)
        _colors.Add(Color.FromArgb(c));
      InvokeColorsChanged(new ColorsChangedEventArgs());
      }
    }

  /// <summary>
  /// Returns the Color at index <paramref name="index"/>.
  /// </summary>
  /// <param name="index">Index of the color to return</param>
  /// <returns>_colors[index]</returns>
  public Color this[int index] { get { Debug.Assert(index >= 0 && index < _colors.Count); return _colors[index]; } }

  /// <summary>
  /// Default Constructor
  /// ONLY for XML serialization, do not use unless you really know what you're doing.
  /// </summary>
  public ColorMap()
    {
    }
  }


Wie gesagt, Serialisierung klappt wie gewünscht und erwartet. Bei der Derserialisierung bleibt _colors aber null und laut debugger wird set__argbColors() nie aufgerufen. Jemand ne Idee woran das liegt? Bin ich irgendwie gerade betriebsblind und übersehe etwas?

Danke und liebe Grüße,
Christian
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4708
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Sa 09.06.12 12:56 
Vermutlich weil beim deserialisieren der _argbColors setter nicht gebraucht wird sondern nur der getter. Die Serialisierung wird die Enzelelemente der Liste füllen (aka ColorMap._argbColors[0] = deserialierter Int). Der Serialisierer aber wird nicht von sich aus auf die Idee kommen eine List<Int> zu erstellen um sie deiner Property zuzuweisen.

Ich würde ColorMap das _colors Feld direkt erzeugen lassen und den Setter für _argbColors weglassen.
Schulteatq Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 16



BeitragVerfasst: Sa 09.06.12 13:26 
Ja, so wird es sein - das erklärt auch, warum wärend der Deserialisierung der getter aufgerufen wird. Danke.

user profile iconRalf Jansen hat folgendes geschrieben Zum zitierten Posting springen:
Ich würde ColorMap das _colors Feld direkt erzeugen lassen und den Setter für _argbColors weglassen.

Da verstehe ich jetzt leider nicht ganz, wie das zur (de)serialisierung von _colors beiträgt?

Ich könnte natürlich _argbColors zu einer normalen Variable machen und vor der Serialisierung eine Methode aufrufen, die _argbColors baut, und nach der Deserialisierung eine Methode aufrufen, die _colors aus _argbColors wiederherstellt. Das wäre aber sehr umständlich, weil das dann an jeder Stelle wo eine ColorMap verwendet wird passieren müsste.

Gibt es einen eleganteren Weg das zu automatisieren? _colors direkt zu serialisieren geht ja leider nicht, da Color nicht serialisierbar ist. Die einzige halbwegs schöne Alternative, die ich gerade sehe ist eine serialisierbare Wrapperklasse um Color zu bauen und diese zu verwenden, was aber auch wieder unschön ist, da Color sealed ist.
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4708
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Sa 09.06.12 13:36 
Zitat:
Da verstehe ich jetzt leider nicht ganz, wie das zur (de)serialisierung von _colors beiträgt?


ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
[Serializable]
public class ColorMap
{
    private List<int> _colors = new List<int>();        

    public List<int> _argbColors
    {
        get
        {
            return _colors;
        }
    }

    public Color this[int index] { get { return Color.FromArgb(_colors[index]); } }
}

Für diesen Beitrag haben gedankt: Schulteatq
Schulteatq Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 16



BeitragVerfasst: Sa 09.06.12 13:44 
Ah ok, das ist natürlich auch eine funktionierende Variante, im Zweifelsfall sogar schöner als meine SerializableColor-Implementierung (die dank impliziter Operatoren nicht so häßlich wie befürchtet ist).

Ich werd nochmal ein wenig drüber nachdenken für welche Variante ich mich jetzt entscheide. Vielen lieben Dank!