Ist schon spät, daher guck ich mir das genauer erst morgen an.
Auf jeden Fall eine sehr nützliche Funktion
Was mir direkt auffällt: Ich würde zum einen einen StringBuilder verwenden, welchen Du für die Rekursion auch als Parameter an die Funktion übergeben können solltest. Das sollte schneller sein und weniger Speicher verbrauchen als mit Strings zu arbeiten.
Außerdem würde ich versuchen, ein paar Caching-Funktionen einzubauen. So braucht man für einen Typ ja nur einmal die PropertyInfos abrufen, die kann man ja dann cachen.
//edit:
Noch eine weitere Idee: Man cached nicht nur die PropertyInfos, sondern cached für jeden Typ die komplette Methode, nach der er serialisiert wird. Man definiert einen solchen Delegate:
C#-Quelltext
1:
| private delegate void SerializeDelegate(Object o, StringBuilder sb); |
und hat ein Dictionary:
C#-Quelltext
1:
| private Dictionary<Type, SerializeDelegate> serializers; |
Dann braucht man die ganzen Fall-Unterscheidungen nur einmal pro Typ machen, ab da ruft man nur noch den korrekten Delegate aus dem Dictionary ab.
Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".