tun kann ich die folgende Konsolenanwendung haben:XML-Serialisierung ähnlich dem, was Json.Net
using System;
using System.IO;
using System.Xml.Serialization;
using Newtonsoft.Json;
namespace OutputApp
{
public class Foo
{
public object Value1 { get; set; }
public string Value2 { get; set; }
}
public class Bar
{
public int Arg1 { get; set; }
public double Arg2 { get; set; }
}
class Program
{
public static Foo CreateFooBar()
{
return new Foo
{
Value1 = new Bar
{
Arg1 = 123,
Arg2 = 99.9
},
Value2 = "Test"
};
}
public static string SerializeXml(object obj)
{
using (var stream = new MemoryStream())
{
using (var reader = new StreamReader(stream))
{
var serializer = new XmlSerializer(obj.GetType());
serializer.Serialize(stream, obj);
stream.Position = 0;
return reader.ReadToEnd();
}
}
}
static void Main(string[] args)
{
var fooBar = CreateFooBar();
// Using Newtonsoft.Json
var json = JsonConvert.SerializeObject(fooBar, Formatting.Indented);
var xnode = JsonConvert.DeserializeXNode(json, "RootElement");
var xml = xnode.ToString();
// Using XmlSerializer, throws InvalidOperationException
var badXml = SerializeXml(fooBar);
Console.ReadLine();
}
}
}
Ich habe zwei Klassen. Klasse Foo
und Klasse Bar
. Die Klasse Foo
hat eine Eigenschaft des Typs object
. Dies ist eine Voraussetzung, da es sich um einen Vertrag handelt, der eine Vielzahl von Objekten enthalten kann und daher kann ich die Eigenschaft nicht auf einen konkreten Typ oder ein generisches Objekt festlegen.
Jetzt komponiere ich ein Dummy fooBar
Objekt mit der CreateFooBar()
Methode. Danach serialisiere ich es zunächst in JSON, was wunderbar mit Json.Net funktioniert. Dann verwende ich Json.Net's XML-Konverter-Methode, um die JSON-String in ein XNode
Objekt zu konvertieren. Es funktioniert auch gut.
Der Ausgang der beiden ist die folgende:
{
"Value1": {
"Arg1": 123,
"Arg2": 99.9
},
"Value2": "Test"
}
<RootElement>
<Value1>
<Arg1>123</Arg1>
<Arg2>99.9</Arg2>
</Value1>
<Value2>Test</Value2>
</RootElement>
Jetzt, während dies funktioniert, es ist sicherlich nicht sehr schön, weil ich in Json serialisiert haben erst danach sie in XML-Serialisierung. Ich möchte direkt in XML serialisieren.
Wenn ich die XmlSerializer
, dies zu tun habe ich den berüchtigten InvalidOperationExceptoin, weil ich nicht meine Klassen mit dem Attribut XmlInclude
dekorieren oder hat eine der other workarounds.
InvalidOperationException
Der Typ OutputApp.Bar war nicht zu erwarten. Verwenden Sie das SoapInclude-Attribut XmlInclude oder , um Typen anzugeben, die statisch nicht bekannt sind.
Keine der Abhilfen für das XmlSerializer ist eine gute Lösung IMHO und ich habe nicht die Notwendigkeit, es sehen, wie es durchaus möglich ist, ein Objekt in XML ohne
crappy
Attribute zu serialisiert.
Kennt jemand einen guten Xml Serializer in .NET, der dies tun kann oder gibt es einen Plan, diese Funktion zu Json.Net hinzuzufügen?
Irgendwelche Ideen?
Update1
Ich bin nicht Attribute zu verwenden, im Gegensatz, aber es muss Sinn machen. Was ich an dem Attribut XmlInclude
nicht mag, ist, dass es mich in zirkuläre Abhängigkeiten zwingt. Angenommen, ich habe die Assembly A, die eine Basisklasse definiert, und die Assembly B, die abgeleitete Klassen implementiert. Die Funktionsweise des XmlInclude-Attributs besteht nun darin, dass ich die Basisklasse in Assembly A mit dem Typnamen der untergeordneten Klasse aus Assembly B dekorieren müsste. Das würde bedeuten, dass ich eine zirkuläre Abhängigkeit habe und nein bin!
Update2
ich klarstellen soll, dass ich nicht nach einer Lösung suchen meine Konsolenanwendung erneut Faktor, um es mit dem XmlSerializer
funktioniert, ich bin für einen Weg, um XML suchen serialisiert, was ich dort haben .
Es gab einen Kommentar unten, der erwähnt, dass object
als Datentyp schlechtes Design ist.Ob das stimmt oder nicht, das ist eine ganz andere Diskussion. Der Punkt ist, dass es keinen Grund gibt, warum es nicht in der Lage sein sollte, in XML zu serialisieren, und ich bin neugierig, eine solche Lösung zu finden.
Persönlich finde ich die Erstellung einer "Marker" -Schnittstelle ein schmutziges Design. Es missbraucht eine Schnittstelle, um die Unfähigkeit einer einzelnen .NET-Klasse (XmlSerializer) zu umgehen. Wenn ich jemals die Serialisierungsbibliothek für etwas anderes tauschen würde, wäre die gesamte Markierungsschnittstelle überflüssiges Durcheinander. Ich möchte meine Klassen nicht an einen Serialisierer koppeln.
Ich suche eine elegante Lösung (wenn es eine gibt)?
Da Sie gegen "beschissene Attribute" sind, klingt es so, als wäre Ihr Verstand geschlossen. Sind Sie immer noch bereit, eine Lösung zu versuchen, auch wenn sie Ihrer Meinung nach nicht perfekt ist? – tgolisch
sicher, aber es muss einen Sinn ergeben. Was ich an den Attributen nicht mag, ist, dass es mich in zirkuläre Abhängigkeiten zwingt. Angenommen, ich habe die Assembly A, die eine Basisklasse definiert, und die Assembly B, die abgeleitete Klassen implementiert. Jetzt funktioniert das XmlInclude-Attribut so, dass ich die Basisklasse in Assembly A mit dem Typnamen der Kindklasse aus Assembly B dekorieren müsste. Boom, zirkuläre Abhängigkeit. Das ist ein Nein! – dustinmoris
Wenn Sie XmlSerializer verwenden, sollte es kein Problem mit zirkulären Abhängigkeiten jeglicher Art geben. Könnte nicht einfacher sein :) – ManoDestra