Tagi na forum.

C# 1456 XML 282
SQL 1192 sieci 268
ASP.NET 785 IIS 262
Windows 726 C++ 255
web 608 Html 218
Visual Studio 515 Information Technology 193
SQL Server 425 MSDN 167

pokaż wszystkie tagi na forum

Serializacja klasy odziedziczonej po obiekcie WPF

Cinioo 2011-07-23 16:31:00
0
avatar
 
 
Witam
 
Próbuję zserializować klasę, która jest odziedziczona po obikecie WPF, w poniższym przykładzie po Canvas. Klasa ta ma pola które są typami prostymi jak i obiektami WPF, poniżej Rectangle i Polyline.
Szukam już od paru dni rozwiązania. Wytestowałem już XMLSerializer, XAMLWriter, teraz próbuje użyć DataContractSerializer z WCF. Pierwszy serializuje tylko typy proste i klasa nie może być odziedziczona po klasie pochodzącej z WPFa. XAMLWriter serializuje co prawda klase odziedziczoną, ale tylko jej pola wbudowane z klasy nadrzędnej, natomiast ignoruje pola dodane w klasie pochodnej. DataContractSerializer też sam w sobie nie bardzo chce serializować klasy pochodne po WPF. Dopeiro po zaimplementowaniu mu interfejsu ISerializable zadziałał, jednak nie do końca tak jak tego chcę.
 
Przykładowa klasa:
 
[Kod]public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();

Rectangle rectangle = new Rectangle();
rectangle.Width = 20;
rectangle.Height = 30;

Polyline polyLine = new Polyline();
PointCollection pointCollection = new PointCollection(){new Point(10,10), new Point(30,30), new Point(50,10)};
polyLine.Points = pointCollection;

NewCanvas newCanvas = new NewCanvas("test", rectangle, polyLine);
newCanvas.Width = 120;
newCanvas.Height = 150;

newCanvas.SaveToXML(@"Save.xml");
}
}

[Serializable]
public class NewCanvas : Canvas, ISerializable
{
private string _name;
private Rectangle _rectangle;
private Polyline _polyLine;

public NewCanvas(string name, Rectangle rectangle, Polyline polyLine)
{
_name = name;
_rectangle = rectangle;
_polyLine = polyLine;
}

public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("BaseProperties", XamlWriter.Save(this));
info.AddValue("Name", _name);
info.AddValue("Rectangle", XamlWriter.Save(_rectangle));
info.AddValue("PolyLine", XamlWriter.Save(_polyLine));
}

public NewCanvas(SerializationInfo info, StreamingContext context)
{
//Deserialization implement
}

public void SaveToXML(string fileName)
{
DataContractSerializer ser = new DataContractSerializer(typeof(NewCanvas));
XmlWriterSettings settings = new XmlWriterSettings() { Indent = true };

using (XmlWriter writer = XmlWriter.Create(fileName, settings))
{
ser.WriteObject(writer, this);
writer.Close();
}
}
}




 
Powyższy kod generuje coś takiego:



[Kod]
<?xml version="1.0" encoding="utf-8"?>
<NewCanvas xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns:x="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.datacontract.org/2004/07/Serializacja">
<BaseProperties i:type="x:string" xmlns=""><NewCanvas Width="120" Height="150" xmlns="clr-namespace:Serializacja;assembly=Serializacja" xmlns:av="http://schemas.microsoft.com/winfx/2006/xaml/presentation" /></BaseProperties>
<Name i:type="x:string" xmlns="">test</Name>
<Rectangle i:type="x:string" xmlns=""><Rectangle Width="20" Height="30" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" /></Rectangle>
<PolyLine i:type="x:string" xmlns=""><Polyline Points="10,10 30,30 50,10" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" /></PolyLine>
</NewCanvas>




 
Jak widać, wstawiam nowy element do struktury XML i w nim dodaję pole z klasy. Obiekt
Edytowano 2 razy. Ostatnio 2011-07-23 16:32:21 przez Cinioo.
tagi: WPF   XML


m.iwanowski  2011-07-23 16:35:24 #1
0
avatar
 
 
A chcesz to serializować po to, żeby przesłać WCF'em?--Pozdrawiam
Marcin Iwanowski
 
...::: Jeżeli mój post Ci pomógł, kliknij "Pomógł mi" :::...

Pozdrawiam

Marcin Iwanowski

 

...::: Jeżeli mój post jest rozwiązaniem Twojego problemu, kliknij "Rozwiązanie" :::...

Cinioo  2011-07-23 18:49:22 #1.1
0
avatar
 
 
Nie. Chcę po prostu zapisać do pliku i później odczytać.
Użyłem DataContractSerializera dlatego, że XMLSerializer wywalał błąd gdy próbowałem serializować klasę, która dziedziczy po klasie WPF - tutaj Canvas. XAMLWriter.Save() natomiast nie serializuje pól z mojej klasy pochodnej. WCFowy serializer radzi sobie z taką klasą, ale jak pisałem nie do końca tak jak chce. Poza tym potrafi zapisać "referencyjnie" (w odpowiednim trybie) tzn. że danemu elementowi w strukurze XML przypisuje jakieś ID i jeżeli gdzieś w klasie, bądź innej klasie będzie odwołanie na dany element, to po prostu wstawi w tym miejscu ID. Przykład tutaj http://www.ikriv.com/en/prog/info/dotnet/XmlSerializers/summary.php?backUrl=index.shtml%23summary&sample=ObjectGraph&serializer=WCF-ref
 
Ogólnie potrzebuje zapisać klase, która dziedziczy po klasie WPF i ma w sobie pola typów: prostych, klasy zwykłe, klasy WPF lub klasy odziedziczone po nim, listy z elementami WPF itd. Ogólnie wszystko ogranicza się do typów prostych i typów pochodzących z WPF. Czy to będzie serializer z WCF czy inny nie miało by większego znaczenia, tylko że tamte poprzednie co wymieniłem nie radzą sobie, albo ja coś źle robię. Szukam już pare dni na gogle i na nic nie mogę trafić co by rozwiązało mój problem.

m.iwanowski  2011-07-23 20:39:44 #1.1.1
0
avatar
 
 
Jeżeli Twoim zamiarem jest jedynie zapisać a później odczytać dany obiekt to najwygodniej byłoby Ci skorzystać wyłącznie z klasy XamlWriter (a później XamlReader).
Skaskuj wszystkie metody które masz teraz do serializacji i w funkcji SaveToXml wywołaj tylko XamlWriter.Save(this); jednakże żeby to zadziałało tak jak tego oczekujesz musisz jeszcze jedynie zrobić publiczne właściwości dla każdego z obiektów który chcesz także zapisać do pliku z Twojego canvas, np:



[Kod]
private Rectangle Rect
{
get { return this._rectangle; }
set { this._rectangle = value; }
}





I to tyle.
--
Pozdrawiam
Marcin Iwanowski
 
...::: Jeżeli mój post Ci pomógł, kliknij "Pomógł mi" :::...

Edytowano 1 raz. Ostatnio 2011-07-23 20:40:22 przez m.iwanowski.

Pozdrawiam

Marcin Iwanowski

 

...::: Jeżeli mój post jest rozwiązaniem Twojego problemu, kliknij "Rozwiązanie" :::...

Cinioo  2011-07-24 11:27:57 #1.1.1.1
0
avatar
 
 
Dzięki! Działa!
 



[Kod]
public class NewCanvas : Canvas
{
public string _name { get; set; }
public Rectangle _rectangle { get; set; }
public Polyline _polyLine { get; set; }

...

public void SaveToXML(string fileName)
{
TextWriter WriteFileStream = new StreamWriter(fileName);
XamlWriter.Save(this, WriteFileStream);
}
}




Wynik:



[Kod]
<NewCanvas _name="test" Width="120" Height="150" xmlns="clr-namespace:Serializacja;assembly=Serializacja" xmlns:av="http://schemas.microsoft.com/winfx/2006/xaml/presentation"><NewCanvas._rectangle><av:Rectangle Width="20" Height="30" /></NewCanvas._rectangle><NewCanvas._polyLine><av:Polyline Points="10,10 30,30 50,10" /></NewCanvas._polyLine></NewCanvas>




Wiedziałem, że XMLSerializer wymaga publicznych pól, ale jakoś niedoczytałem, że XAMLWriter.Save() również, a przez te całe kombinowanie z różnymi serializerami nie spróbowałem.
Teraz jest mniej więcej tak jak tego oczekiwałem. Dziękuje za pomoc.

Udziel odpowiedzi

avatar
Treść wpisu:

Zaloguj się lub Zarejestruj się aby wykonać tę czynność.

Idź na górę strony