Feedback

C# - generische De-/ Serialisierung von Objekten in XML und Binär

Veröffentlicht von am 14.02.2008
(1 Bewertungen)
Mit dieser Klasse kann man Objekte Serialisieren und deserialisieren in XML oder in binär Dateien.
Die Klasse ist generisch.
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Xml.Serialization;

namespace Veasel.Serialisierung
{
	public enum SerialisierungTyp
	{
		Binary,
		XML
	}
	public class Serialisierung<T>
	{
		FileStream fs = null;

		#region öffentliche Methoden
		public void SaveToFile(T objectToSave, string FileName, SerialisierungTyp typ)
		{
			switch (typ)
			{
				case SerialisierungTyp.Binary: SaveBinary(objectToSave, FileName);
					break;
				case SerialisierungTyp.XML: SaveXML(objectToSave, FileName);
					break;
				default:
					break;
			}
		}

		public T LoadFromFile(string FileName, SerialisierungTyp typ)
		{
			T serializedObject = default(T);
			switch (typ)
			{
				case SerialisierungTyp.Binary: serializedObject = LoadBinary(FileName, serializedObject); 
					break;
				case SerialisierungTyp.XML: serializedObject = LoadXML(serializedObject, FileName);
					break;
				default:
					break;
			}
			return serializedObject;
		}
		#endregion

		#region private Methoden
		#region Binary
		private void SaveBinary(T obj, string filename)
		{
			try
			{
				fs = new FileStream(filename, FileMode.OpenOrCreate, FileAccess.Write);
				BinaryFormatter bf = new BinaryFormatter();
				bf.Serialize(fs, obj);
			}
			finally
			{
				if (fs != null)
				{
					fs.Flush();
					fs.Close();
				}
			}
		}

		private T LoadBinary(string filename, T obj)
		{
			try
			{
				fs = new FileStream(filename, FileMode.Open, FileAccess.Read);
				BinaryFormatter bf = new BinaryFormatter();
				obj = (T)bf.Deserialize(fs);
			}
			finally
			{
				fs.Flush();
				fs.Close();
			}
			return obj;
		}
		#endregion

		#region XML

		private void SaveXML(T obj, string filename)
		{
			try
			{
				fs = new FileStream(filename, FileMode.OpenOrCreate, FileAccess.Write);
				XmlSerializer bf = new XmlSerializer(typeof(T));
				bf.Serialize(fs, obj);
			}
			finally
			{
				if (fs != null)
				{
					fs.Flush();
					fs.Close();
				}
			}
		}

		private T LoadXML(T obj, string filename)
		{
			try
			{
				fs = new FileStream(filename, FileMode.Open, FileAccess.Read);
				XmlSerializer bf = new XmlSerializer(typeof(T));
				obj = (T)bf.Deserialize(fs);
			}
			finally
			{
				fs.Flush();
				fs.Close();
			}
			return obj;
		}
		#endregion
		#endregion
	}
}

Abgelegt unter Serialisierung, Serialization.

1 Kommentare zum Snippet

AI schrieb am 19.01.2026:
Das Snippet stammt aus der späten .NET-2.0-Zeit und zeigt einen damals üblichen Ansatz, Objekte generisch per XML- oder Binärserialisierung zu speichern und wieder zu laden. Der grundsätzliche Wunsch nach generischer Serialisierung ist weiterhin nachvollziehbar, die konkrete Umsetzung ist heute jedoch in mehreren Punkten problematisch und teilweise sogar gefährlich.

Analyse nach heutigen Kriterien:
- Sicherheit: BinaryFormatter gilt seit Jahren als unsicher und ist inzwischen offiziell als obsolete markiert. Bei Deserialisierung aus nicht vollständig vertrauenswürdigen Quellen besteht ein reales Risiko für Remote Code Execution. Neue Anwendungen sollten BinaryFormatter grundsätzlich nicht mehr verwenden.
- Korrektheit: Die Methoden erzwingen keine klaren Constraints an T. Nicht jedes Objekt ist sinnvoll oder korrekt serialisierbar (z. B. fehlender parameterloser Konstruktor bei XML).
- Robustheit: Exceptions werden nicht gezielt behandelt oder angereichert. Fehler bei inkompatiblen Typen, Versionierungsproblemen oder kaputten Streams sind schwer diagnostizierbar.
- Performance/Allokationen: XmlSerializer erzeugt intern dynamische Assemblies und ist teuer beim ersten Aufruf. Das ist akzeptabel bei seltenen Operationen, aber problematisch in Hot-Paths.
- Thread-Safety: XmlSerializer ist nicht garantiert thread-safe, wenn Instanzen geteilt werden.
- Cloud/Container: BinaryFormatter ist in modernen .NET-Versionen eingeschränkt oder deaktiviert. Datei-basierte Serialisierung ist in Cloud-Umgebungen oft ungeeignet.
- Versionierung: Weder XML- noch Binärserialisierung sind hier versionstolerant. Kleine Modelländerungen führen schnell zu Laufzeitfehlern.

Grundsätzliches Architekturproblem:
Die Methoden versuchen, eine Serialisierung für alle Zwecke anzubieten. Das verschleiert, dass unterschiedliche Szenarien unterschiedliche Formate und Regeln erfordern.

Modernisierte Beispielvariante (XML, streambasiert, klar begrenzt):

using System;
using System.IO;
using System.Xml.Serialization;

public static class XmlSerialization
{
public static void Serialize<T>(Stream target, T value)
{
if (target is null) throw new ArgumentNullException(nameof(target));
var serializer = new XmlSerializer(typeof(T));
serializer.Serialize(target, value);
}

public static T Deserialize<T>(Stream source)
{
if (source is null) throw new ArgumentNullException(nameof(source));
var serializer = new XmlSerializer(typeof(T));
return (T)serializer.Deserialize(source)!;
}
}


Warum das heute objektiv besser ist:
- Sicherheit: Kein BinaryFormatter, kein impliziter Code-Load.
- Flexibilität: Streams statt Dateien erlauben Files, Memory, Netzwerk, Cloud Storage.
- Wartbarkeit: Der Aufrufer entscheidet explizit über Format, Speicherort und Lebensdauer.
- Architekturklarheit: Keine falsche Abstraktion, sondern gezielte APIs.

Security-Realitätscheck:
Generische Deserialisierung ist immer ein Angriffspunkt. Daten sollten nur aus vertrauenswürdigen Quellen stammen und bewusst deserialisiert werden.
 

Logge dich ein, um hier zu kommentieren!