Serializing? How to?

  • Thread starter Thread starter TomB
  • Start date Start date
T

TomB

I'm trying to persist configuration information to disk. I'm going crazy.
This is what I've tried.

-------
TextWriter writer=new StreamWriter(xmlLoc);

XmlSerializer x = new XmlSerializer(typeof(IP));

for (int i=0;i<iplist.Count;i++)

{

ip=(IP) iplist;

x.Serialize(writer,ip);

}


writer.Close();

-------

It does write it, and it even looks kind of close. But it's not
right....this is what's output.

<IP xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

<HostName>www.microsoft.com</HostName>

<CommonName>microsoft</CommonName>

<CurrentStatus>0</CurrentStatus>

<Flag>PingDown</Flag>

<NextPing>2004-03-29T21:46:38.6484525-05:00</NextPing>

</IP><?xml version="1.0" encoding="utf-8"?>

<IP xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

<HostName>www.google.com</HostName>

<CommonName>Google</CommonName>

<CurrentStatus>0</CurrentStatus>

<Flag>PingDown</Flag>

<NextPing>2004-03-29T21:46:38.6484525-05:00</NextPing>

</IP>



As you can see. It's putting the <?xml version="1.0" encoding="utf-i"?>
line in twice, so I assume that I'm way off here.

All of the tutorials and how-tos talk about creating xsd's and so forth. Is
this correct? As you can see this is not a complicated class-that I'm
trying to persist.


Any help is greatly appreciated.



Tom
 
It seems evident that your "iplist.Count" is 2. All that's happening is
that you are writing two separate serializations to the same stream and the
XmlSerializer has no way of knowing they are all part of the same
serialization "group".

What you could do is something like this, which would serialize them all
together (console app to demo):
using System;
using System.IO;
using System.Xml.Serialization;
namespace SerializeArray
{
class Class1
{
[STAThread]
static void Main(string[] args)
{
IP[] ips = new IP[2];
ips[0] = new IP("127.0.0.1");
ips[1] = new IP("255.255.0.0");
XmlSerializer xmls = new XmlSerializer(typeof(IP[]), new Type[]
{typeof(IP)});
MemoryStream stream = new MemoryStream();
xmls.Serialize(stream, ips);
Console.WriteLine(System.Text.Encoding.ASCII.GetString(stream.ToArray()));
}
}
public class IP
{
public IP() {}
public IP(string host)
{
HostName = host;
}
public string HostName;
}
}
 
Each call to serialize writes a new xml document to the file. Try
serializing an array instead:

TextWriter writer=new StreamWriter(xmlLoc);
try
{
XmlSerializer x = new XmlSerializer(typeof(IP[]));

x.Serialize(writer,iplist.ToArray(typeof(IP)));
}
finally
{
writer.Close();
}

This will result in

<ArrayOfIP>
<IP>...</IP>
<IP>...</IP>
<ArrayOfIP>

/Hugo
 
Here is the code ...

You must modify it by Yourself but ... it may be helpfull





using System;

using System.IO;

using System.Xml;

using System.Text;

using System.Threading;

using System.Xml.Serialization;

namespace Datacomp.DMiscellaneous

{

/// <summary>

/// Obs³uga serializacji obiektów.

/// </summary>

public class Serializers

{

#region DeserializeObject [2]

/// <summary>

/// Deserializuje obiekt z wskazanego pliku xml.

/// (generuje informacjê o procesie).

/// </summary>

/// <param name="pDeserializedObject">Zmienna któr± wype³niæ
warto¶ci±.</param>

/// <param name="pType">Typ deserializowanego obiektu.</param>

/// <param name="pFileName">Nazwa pliku z którego deserializowaæ.</param>

/// <returns>Czy deserializacja siê powiod³a?</returns>

public static bool DeserializeObject(out object pDeserializedObject,Type
pType,string pFileName)

{

return DeserializeObject(out pDeserializedObject,pType,pFileName,false);

}

/// <summary>

/// Deserializuje obiekt z wskazanego pliku xml.

/// (generuje informacjê o procesie).

/// </summary>

/// <param name="pDeserializedObject">Zmienna któr± wype³niæ
warto¶ci±.</param>

/// <param name="pType">Typ deserializowanego obiektu.</param>

/// <param name="pFileName">Nazwa pliku z którego deserializowaæ.</param>

/// <param name="pUnattend">Czy cichy tryb?</param>

/// <returns>Czy deserializacja siê powiod³a?</returns>

public static bool DeserializeObject(out object pDeserializedObject,Type
pType,string pFileName

,bool pUnattend)

{

pDeserializedObject = null;

if(pFileName == null || !File.Exists(pFileName))

{

return false;

}

bool result = false;

try

{

XmlTextReader xTr = new XmlTextReader(pFileName);

XmlSerializer xS = new XmlSerializer(pType);

try

{

if(xS.CanDeserialize(xTr))

{

pDeserializedObject = xS.Deserialize(xTr);

result = true;

}

}

catch(ThreadAbortException)

{

// Koniec w±tku ...

}

catch(Exception e)

{

ExceptionHandlers.ExceptionHandler(e

,"nie mo¿na zdeserializowaæ obiektu ("+pFileName+")."

,DMCore.SystemMainForm,pUnattend);

}

finally

{

xTr.Close();

}

}

catch(ThreadAbortException)

{

// Koniec w±tku ...

}

catch(Exception e)

{

ExceptionHandlers.ExceptionHandler(e

,"nie mo¿na rozpocz±æ procesu deserializacji.\r\n("+pFileName+")"

,DMCore.SystemMainForm,pUnattend);

}

return result;

}

#endregion

#region SerializeObject [2]

/// <summary>

/// Serializuje obiekt do wskazanego pliku xml.

/// (generuje informacjê o procesie).

/// </summary>

/// <param name="pObject">Obiekt który serializowaæ.</param>

/// <param name="pFileName">Nazwa pliku do którego serializowaæ.</param>

/// <returns>Czy serializacja zakoñczona pomy¶lnie?</returns>

public static bool SerializeObject(object pObject,string pFileName)

{

return SerializeObject(pObject,pFileName,false);

}

/// <summary>

/// Serializuje obiekt do wskazanego pliku xml.

/// (generuje informacjê o procesie).

/// </summary>

/// <param name="pObject">Obiekt który serializowaæ.</param>

/// <param name="pFileName">Nazwa pliku do którego serializowaæ.</param>

/// <param name="pUnattend">Czy cichy tryb?</param>

/// <returns>Czy serializacja zakoñczona pomy¶lnie?</returns>

public static bool SerializeObject(object pObject,string pFileName,bool
pUnattend)

{

if(pObject == null || !DMCore.CheckFile(ref
pFileName,"xml",null,false,false,true))

{

return false;

}

bool result = false;

try

{

XmlTextWriter xTw = new XmlTextWriter(pFileName,Encoding.Default);

XmlSerializer xS = new XmlSerializer(pObject.GetType());

try

{

xS.Serialize(xTw,pObject);

result = true;

}

catch(ThreadAbortException)

{

// Koniec w±tku ...

}

catch(Exception e)

{

ExceptionHandlers.ExceptionHandler(e

,"nie mo¿na zserializowaæ obiektu ("+pFileName+")."

,DMCore.SystemMainForm,pUnattend);

}

finally

{

xTw.Close();

}

}

catch(ThreadAbortException)

{

// Koniec w±tku ...

}

catch(Exception e)

{

ExceptionHandlers.ExceptionHandler(e

,"nie mo¿na rozpocz±æ procesu serializacji.\r\n("+pFileName+")"

,DMCore.SystemMainForm,pUnattend);

}

return result;

}

#endregion

}

}
 
Well jeez. That was easy. Thanks for your help. Could you tell me, why
you had to create a new type in this line
XmlSerializer xmls = new XmlSerializer(typeof(IP[]), new
Type[]{typeof(IP)});

the examples I had seen (although they weren't arrays) just had .....new
XmlSerializer(typeof(IP[]))

Thanks a lot.

TomB


Richard A. Lowe said:
It seems evident that your "iplist.Count" is 2. All that's happening is
that you are writing two separate serializations to the same stream and the
XmlSerializer has no way of knowing they are all part of the same
serialization "group".

What you could do is something like this, which would serialize them all
together (console app to demo):
using System;
using System.IO;
using System.Xml.Serialization;
namespace SerializeArray
{
class Class1
{
[STAThread]
static void Main(string[] args)
{
IP[] ips = new IP[2];
ips[0] = new IP("127.0.0.1");
ips[1] = new IP("255.255.0.0");
XmlSerializer xmls = new XmlSerializer(typeof(IP[]), new Type[]
{typeof(IP)});
MemoryStream stream = new MemoryStream();
xmls.Serialize(stream, ips);
Console.WriteLine(System.Text.Encoding.ASCII.GetString(stream.ToArray()));
}
}
public class IP
{
public IP() {}
public IP(string host)
{
HostName = host;
}
public string HostName;
}
}

--
C#, .NET and Complex Adaptive Systems:
http://blogs.geekdojo.net/Richard
TomB said:
I'm trying to persist configuration information to disk. I'm going crazy.
This is what I've tried.

-------
TextWriter writer=new StreamWriter(xmlLoc);

XmlSerializer x = new XmlSerializer(typeof(IP));

for (int i=0;i<iplist.Count;i++)

{

ip=(IP) iplist;

x.Serialize(writer,ip);

}


writer.Close();

-------

It does write it, and it even looks kind of close. But it's not
right....this is what's output.

<IP xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

<HostName>www.microsoft.com</HostName>

<CommonName>microsoft</CommonName>

<CurrentStatus>0</CurrentStatus>

<Flag>PingDown</Flag>

<NextPing>2004-03-29T21:46:38.6484525-05:00</NextPing>

</IP><?xml version="1.0" encoding="utf-8"?>

<IP xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

<HostName>www.google.com</HostName>

<CommonName>Google</CommonName>

<CurrentStatus>0</CurrentStatus>

<Flag>PingDown</Flag>

<NextPing>2004-03-29T21:46:38.6484525-05:00</NextPing>

</IP>



As you can see. It's putting the <?xml version="1.0" encoding="utf-i"?>
line in twice, so I assume that I'm way off here.

All of the tutorials and how-tos talk about creating xsd's and so forth. Is
this correct? As you can see this is not a complicated class-that I'm
trying to persist.


Any help is greatly appreciated.



Tom

 
You don't need it, actually. In more complicated object graphs you need to
specify all the types that the XmlSerializer will encounter in the object,
and you do this by building a Type array of all the types and passing it as
the second parameter. new Type[] {...} is just a shortcut to doing so. But
in the case of an array you don't need to specify both the array and the
element - that was just me adding it in 'cause I thought I had to.

Richard

--
C#, .NET and Complex Adaptive Systems:
http://blogs.geekdojo.net/Richard
TomB said:
Well jeez. That was easy. Thanks for your help. Could you tell me, why
you had to create a new type in this line
XmlSerializer xmls = new XmlSerializer(typeof(IP[]), new
Type[]{typeof(IP)});

the examples I had seen (although they weren't arrays) just had .....new
XmlSerializer(typeof(IP[]))

Thanks a lot.

TomB


Richard A. Lowe said:
It seems evident that your "iplist.Count" is 2. All that's happening is
that you are writing two separate serializations to the same stream and the
XmlSerializer has no way of knowing they are all part of the same
serialization "group".

What you could do is something like this, which would serialize them all
together (console app to demo):
using System;
using System.IO;
using System.Xml.Serialization;
namespace SerializeArray
{
class Class1
{
[STAThread]
static void Main(string[] args)
{
IP[] ips = new IP[2];
ips[0] = new IP("127.0.0.1");
ips[1] = new IP("255.255.0.0");
XmlSerializer xmls = new XmlSerializer(typeof(IP[]), new Type[]
{typeof(IP)});
MemoryStream stream = new MemoryStream();
xmls.Serialize(stream, ips);
Console.WriteLine(System.Text.Encoding.ASCII.GetString(stream.ToArray()));
}
}
public class IP
{
public IP() {}
public IP(string host)
{
HostName = host;
}
public string HostName;
}
}

--
C#, .NET and Complex Adaptive Systems:
http://blogs.geekdojo.net/Richard
TomB said:
I'm trying to persist configuration information to disk. I'm going crazy.
This is what I've tried.

-------
TextWriter writer=new StreamWriter(xmlLoc);

XmlSerializer x = new XmlSerializer(typeof(IP));

for (int i=0;i<iplist.Count;i++)

{

ip=(IP) iplist;

x.Serialize(writer,ip);

}


writer.Close();

-------

It does write it, and it even looks kind of close. But it's not
right....this is what's output.

<IP xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

<HostName>www.microsoft.com</HostName>

<CommonName>microsoft</CommonName>

<CurrentStatus>0</CurrentStatus>

<Flag>PingDown</Flag>

<NextPing>2004-03-29T21:46:38.6484525-05:00</NextPing>

</IP><?xml version="1.0" encoding="utf-8"?>

<IP xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

<HostName>www.google.com</HostName>

<CommonName>Google</CommonName>

<CurrentStatus>0</CurrentStatus>

<Flag>PingDown</Flag>

<NextPing>2004-03-29T21:46:38.6484525-05:00</NextPing>

</IP>



As you can see. It's putting the <?xml version="1.0" encoding="utf-i"?>
line in twice, so I assume that I'm way off here.

All of the tutorials and how-tos talk about creating xsd's and so
forth.
Is
this correct? As you can see this is not a complicated class-that I'm
trying to persist.


Any help is greatly appreciated.



Tom

 
Back
Top