The problem is simple, I want to create a method to serialize and another to open it by passing any object structure. I have the following which is what I believed should work but, guess what, it doesn't:
List<string> list = new List<string>();
list.Add("aaa");
list.Add("bbb");
FileSystem.SerializeToFile(list, "");
List<string> anotherList = FileSystem.OpenSerialized(typeof(List<string>), "");
public class FileSystem
{
public static void SerializeToFile(object toSerialize, string fileName)
{
XmlSerializer writer = new XmlSerializer(typeof(object));
StreamWriter file = new StreamWriter(fileName);
writer.Serialize(file, toSerialize);
file.Close();
}
public static object OpenSerialized(Type type, string fileName)
{
XmlSerializer serializer = new XmlSerializer(typeof(object));
StreamReader reader = new StreamReader(fileName);
object something = serializer.Deserialize(reader);
return something;
}
}
The serializer’s constructor requires a reference to the type of object it should work, slightly modified your code to fit to requirement.
public class FileSystem
{
public static void SerializeToFile<T>(T toSerialize, string fileName)
{
XmlSerializer writer = new XmlSerializer(typeof(T));
StreamWriter file = new StreamWriter(fileName);
writer.Serialize(file, toSerialize);
file.Close();
}
public static T OpenSerialized<T>(string fileName)
{
XmlSerializer serializer = new XmlSerializer(typeof(T));
StreamReader reader = new StreamReader(fileName);
object something = serializer.Deserialize(reader);
return (T)something;
}
}
and now we can use this as
List<string> list = new List<string>();
list.Add("aaa");
list.Add("bbb");
FileSystem.SerializeToFile(list, #"d:\test.txt");
List<string> anotherList = FileSystem.OpenSerialized<List<string>>(#"d:\test.txt");
Related
I have a class like this:
public class Response
{
public String AdditionalData = "";
public Boolean Success = false;
public int ErrorCode = 0;
public int WarningCode = 0;
public Transaction TransactionInfo = null;
public PosInfo PosInformation = null;
}
and i can serialize this successfully. but when i serialize this class 2 times and save it in a XML file,multi root error appear in XML editor. i know it needs a XML element to be root to surround other tags, but i don't know how to add root element in a serialize code.
sterilizer class is below:
public class Serializer
{
public void XMLSerializer(Response response)
{
string path = "D:/Serialization.xml";
FileStream fs;
XmlSerializer xs = new XmlSerializer(typeof(Response));
if(!File.Exists(path))
{
fs = new FileStream(path, FileMode.OpenOrCreate);
}
else
{
fs = new FileStream(path, FileMode.Append);
}
StreamWriter sw = new StreamWriter(fs);
XmlTextWriter xw = new XmlTextWriter(sw);
xw.Formatting = System.Xml.Formatting.Indented;
xs.Serialize(xw, response);
xw.Flush();
fs.Close();
}
}
I would recommend improving your code to at least take care of disposable resources.
using Statement
Provides a convenient syntax that ensures the correct use of IDisposable objects.
public class Serializer
{
public void XMLSerializer(Response response)
{
string path = "D:/Serialization.xml";
var xs = new XmlSerializer(typeof(Response));
using (var fs = new FileStream(path, FileMode.OpenOrCreate))
{
using (var sw = new StreamWriter(fs))
{
using (var xw = new XmlTextWriter(sw))
{
xw.Formatting = System.Xml.Formatting.Indented;
xs.Serialize(xw, response);
xw.Flush();
}
}
fs.Close();
}
}
}
I'm trying to save lists of object to a xml file. But when I'm save once it delete the before saving. I mean if I save on xml file 1 list of "Radar" and than save on the save xml file list of "Observer" it saves only the last list I save. There is any way to save them both ?
My code to save :
XmlSerializer serializer = new XmlSerializer(typeof(List<Observer>));
using (TextWriter writer = new StreamWriter(#"C:\Users\user\Desktop\MapSample\bin\Debug\ListObserver.xml"))
{
serializer.Serialize(writer, list);
}
Hope you understand. Thanks in advice.
Edit :
I creat new object that contain the lists as a properties. And now All the list in one xml file.
The object :
[Serializable()]
public class SaveObject
{
public List<Radar> listRadars = new List<Radar>();
public List<Ikun> listIkuns = new List<Ikun>();
public List<Observer> listObservers = new List<Observer>();
public XmlSerializer ser;
public SaveObject(List<Observer> listObservers, List<Ikun> listIkuns,List<Radar> listRadars)
{
this.listIkuns = listIkuns;
this.listRadars = listRadars;
this.listObservers = listObservers;
}
public SaveObject()
{
ser = new XmlSerializer(this.GetType());
}
}
The serialize function :
public void Serialize(SaveObject SO)
{
if (IfPathToSave) // Select save - not auto !
{
XmlSerializer serializer = new XmlSerializer(typeof(SaveObject));
using (TextWriter writer = new StreamWriter(FilePath))
{
serializer.Serialize(writer, SO);
}
}
else // auto save !
{
XmlSerializer serializer = new XmlSerializer(typeof(SaveObject));
using (TextWriter writer = new StreamWriter(#"C:\Users\user\Desktop\MapSample\bin\Debug\AutoSave.xml"))
{
serializer.Serialize(writer, SO);
}
}
}
Hope it will help any one sometime. Enjoy. :)
If you have 2 lists and doing it this way (wrong)
var serializer = new XmlSerializer(typeof(List<Observer>));
using (var writer = new StreamWriter(#"C:\Users\user\Desktop\MapSample\bin\Debug\ListObserver.xml"))
serializer.Serialize(writer, listA);
using (var writer = new StreamWriter(#"C:\Users\user\Desktop\MapSample\bin\Debug\ListObserver.xml"))
serializer.Serialize(writer, listB);
then listB will overwrite ListObserver.xml content.
You can try this
var serializer = new XmlSerializer(typeof(List<List<Observer>>));
using (var writer = new StreamWriter(#"C:\Users\user\Desktop\MapSample\bin\Debug\ListObserver.xml"))
serializer.Serialize(writer, new List<List<Observer>>(new[] {listA, listB}));
If it doesn't works (for whatever reasons), then simply create serialization object
public class SerializationObject
{
public List<Observer> ListA {get; set;}
public List<Observer> ListB {get; set;}
}
and use it
var serializer = new XmlSerializer(typeof(SerializationObject));
using (var writer = new StreamWriter(#"C:\Users\user\Desktop\MapSample\bin\Debug\ListObserver.xml"))
serializer.Serialize(writer, new SerializationObject() { ListA = listA, ListB = listB });
i have question!!
=============normal===========
class trx()
{
string trx_name;
string type_id;
}
var 0 = new trx(){trx_name="1",trx_name="2"}
---Entity change to xml
[XmlSerializer serializer = new XmlSerializer(typeof(trx));
[serializer.Serialize(File.OpenWrite(#".\MyXml.xml"), o);]
----XML result------
<trx>
<trx_name>1</trx_name>
<type_id>2</type_id>
</trx>
=============================
Q: but i need trx XML
<trx>
<trx_name>a</trx_name>
<trx_name>b</trx_name>
<trx_name>c</trx_name>
<trx_name>d</trx_name>
</trx>
how to solve the question???
Thanks in advance for your help
Something like this.
public class trx
{
public string trx_name { get; set; }
}
public class CustomSerializer
{
private static void Write(string filename)
{
List<trx> trxs = new List<trx>();
trxs.Add(new trx {trx_name = "Name1"});
trxs.Add(new trx {trx_name = "Name2"});
XmlSerializer x = new XmlSerializer(typeof (List<trx>));
TextWriter writer = new StreamWriter(filename);
x.Serialize(writer, trxs);
}
private static List<trx> Read(string filename)
{
var x = new XmlSerializer(typeof (List<trx>));
TextReader reader = new StreamReader(filename);
return (List<trx>) x.Deserialize(reader);
}
}
}
I have a list box that when an item is selected or deselected I want to save the changes to an xml file (so it is always up-to-date on the file and the user does not need a "save" button).
While testing I occasionally am hitting this IOException:
The process cannot access the file 'C:\MyPath\MyFile.xml' because it is being used by another process.
Here is my XML Serialization code:
// Save an object out to the disk
public static void SerializeObject<T>(this T toSerialize, String filename)
{
XmlSerializer xmlSerializer = new XmlSerializer(toSerialize.GetType());
TextWriter textWriter = new StreamWriter(filename);
xmlSerializer.Serialize(textWriter, toSerialize);
}
// Load an object from the disk
private static T DeserialzeObject<T>(String filename) where T : class
{
XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
try
{
TextReader textReader = new StreamReader(filename);
return (T)xmlSerializer.Deserialize(textReader);
}
catch (FileNotFoundException)
{ }
return null;
}
And here is how it is called:
// Save off the list because the visibility has changed
public void WorkItemColumnTypeOnVisibleChanged(int fieldID, Visibility visibility)
{
ColumnFields.SerializeObject(ColumnFields.GetSerializeFilename());
}
The deserialize is the one that is giving the error:
WorkItemColumnTypes savedVersion = DeserialzeObject<WorkItemColumnTypes>(result.GetSerializeFilename());
Is there a way to optimize my connections to the file so that I am not tripping over myself?
Perhaps you need to call Close on the TextWriter objects in your serialization and deserialization methods? Or alternatively use the using construct to force disposal at the end of the block.
Example:
// Save an object out to the disk
public static void SerializeObject<T>(this T toSerialize, String filename)
{
XmlSerializer xmlSerializer = new XmlSerializer(toSerialize.GetType());
using(TextWriter textWriter = new StreamWriter(filename))
{
xmlSerializer.Serialize(textWriter, toSerialize);
}
}
// Load an object from the disk
private static T DeserialzeObject<T>(String filename) where T : class
{
XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
try
{
using(TextReader textReader = new StreamReader(filename))
{
return (T)xmlSerializer.Deserialize(textReader);
}
}
catch (FileNotFoundException)
{ }
return null;
}
This example uses a StringWriter to hold the serialized data, then calling ToString() gives the actual string value:
Person john = new Person();
XmlSerializer xmlSerializer = new XmlSerializer(typeof(Person));
StringWriter stringWriter = new StringWriter();
xmlSerializer.Serialize(stringWriter, john);
string serializedXML = stringWriter.ToString();
Is there any easier/Cleaner way to do this? All of the Serialize() overloads seem to use a Stream or Writer.
UPDATE: Asked a similar question about serializing an IEnumerable via an Extension Method .
Fun with extension methods...
var ret = john.ToXmlString()
public static class XmlTools
{
public static string ToXmlString<T>(this T input)
{
using (var writer = new StringWriter())
{
input.ToXml(writer);
return writer.ToString();
}
}
public static void ToXml<T>(this T objectToSerialize, Stream stream)
{
new XmlSerializer(typeof(T)).Serialize(stream, objectToSerialize);
}
public static void ToXml<T>(this T objectToSerialize, StringWriter writer)
{
new XmlSerializer(typeof(T)).Serialize(writer, objectToSerialize);
}
}
More or less your same solution, just using an extension method:
static class XmlExtensions {
// serialize an object to an XML string
public static string ToXml(this object obj) {
// remove the default namespaces
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add(string.Empty, string.Empty);
// serialize to string
XmlSerializer xs = new XmlSerializer(obj.GetType());
StringWriter sw = new StringWriter();
xs.Serialize(sw, obj, ns);
return sw.GetStringBuilder().ToString();
}
}
[XmlType("Element")]
public class Element {
[XmlAttribute("name")]
public string name;
}
class Program {
static void Main(string[] args) {
Element el = new Element();
el.name = "test";
Console.WriteLine(el.ToXml());
}
}
I created this helper method, but I haven't tested it yet. Updated the code per orsogufo's comments (twice):
private string ConvertObjectToXml(object objectToSerialize)
{
XmlSerializer xmlSerializer = new XmlSerializer(objectToSerialize.GetType());
StringWriter stringWriter = new StringWriter();
xmlSerializer.Serialize(stringWriter, objectToSerialize);
return stringWriter.ToString();
}
Seems like no body actually answered his question, which is no, there is no way to generate an XML string without using a stream or writer object.