C# Writing list of objects into file (easiest way) [duplicate] - c#

This question already has answers here:
How to save/restore serializable object to/from file?
(6 answers)
Closed 4 years ago.
I've got a class of payments:
class Payments
{
public string id; //it must be string because of a method
public string name;
public int payment;
}
And a list of objects:
private List<Payments> database = new List<Payments>();
The question is:
How can I write it in a file (which is located in the solution's folder) in the easiest way? It shouldn't be the most efficient.

You can use Newtonsoft json to easily serialize this list of objects into json and write that to a file,
using (StreamWriter file = File.CreateText(#"f:\payments.json"))
{
JsonSerializer serializer = new JsonSerializer();
serializer.Serialize(file, database);
}

mark your class with [Serializable] attribute and use generic build in serializer class.
You can use it like this
public static void Serialize<T>(T objectToSerialize, string path)
where T : class
{
XmlSerializer serializer = new XmlSerializer(typeof(T));
using (var writer = new StreamWriter(path))
{
serializer.Serialize(writer, objectToSerialize);
}
}
where T is your Payments class and path is your destination path.
In this approach you will serialize it to xml structure, you can easily swap it into binary structure, by using other serializer class. As long as only public properties will by serialized you need to replace your public fields with public properties with public get set accessors.

Related

Generic method reading objects from large XML files in C#

The scenario here is with XML, but I think it might be rather generic related.
I'm trying to deserialize certain types of object from XML files. The procedures are the same for these types, therefore I'm using generic methods. XML files are large, so I'm combining XmlReader and XmlSerializer.
Example of getting the all the objects of a certain type:
public static List<T> GetAll<T>() where T : IMyXml, new()
{
var toReturn = new List<T>();
T t = new T();
string fileName;
// different types are located in different XML files
if (t.Type == XmlTypeEnum.A) fileName = "A.xml";
else if (t.Type == XmlTypeEnum.B) fileName = "B.xml";
else throw ... ;
using (var stream = GetStreamFromResource(fileName)) //get file from embedded resource
{
using (var reader = XmlReader.Create(stream))
{
reader.ReadToFollowing(t.ParentName);
while (reader.ReadToFollowing(t.SelfName))
{
var serializer = new XmlSerializer(typeof(T));
t = (T)serializer.Deserialize(reader.ReadSubtree());
toReturn.Add(t);
}
}
}
return toReturn;
}
While all the types implement a common interface
[XmlType]
public interface IMyXml
{
[XmlIgnore]
string ParentName { get; }
[XmlIgnore]
string SelfName { get; }
[XmlIgnore]
XmlTypeEnum Type { get; }
}
The issues here:
Generic types are not supposed to be if-ed (am I right though?), I have to add an enum as property in order to achieve that
Interface cannot have static properties, I have to instantiate a dummy object to retrieve properties
So the code here looks kinda weird to me, is there a better way to do this?

How to serialize IEnumerable<char> as string & Confusing Deserialization error

Lets say I have the following simple class:
[XmlRoot]
[XmlType("string")]
public partial class eString : IEnumerable<char>
{
string AsString {get;set;}
public IEnumerator<char> GetEnumerator()
{
return this.AsString.ToCharArray().ToList().GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.AsString.ToCharArray().GetEnumerator();
}
public void Add(char character)
{
this.AsString += character;
}
}
Also a namedValue class:
[XmlRoot]
public partial class eNamedValue: KeyValuePair<eString,object>
{...}
And finally,
[XmlRoot]
public partial class eList<T>: List<eNamedValue>
{...}
Now, I serialize eList or any class that inherits from eList using the following XML serializer:
public static XDocument Serialize<T>(this T obj) where T: new()
{
Type tt = obj.GetType();
XmlSerializer xsSubmit = new XmlSerializer(tt);
StringWriter sww = new StringWriter();
XmlWriter writer = XmlWriter.Create(sww);
xsSubmit.Serialize(writer, obj);
return XDocument.Parse(sww.ToString());
}
Serialization works - but my eString is being serialized as a character array, so instead of getting "string", I get individual characters values:
<eNamedList>
<Key>99</Key>
<Key>111</Key>
<Key>100</Key>
<Key>101</Key>...
Also, on Deserialization (SOLVED, see Update#1 below):
public static T Deserialize<T>(this XDocument xml) where T: new()
{
var serializer = new XmlSerializer(typeof(T));
T result;
using (TextReader reader = new StringReader(xml.ToString()))
{
result = (T)serializer.Deserialize(reader);
}
return result;
}
I receive the following error:
System.Runtime.Serialization.SerializationException: Error in line 1 position 111. Expecting element 'eNamedList' from namespace 'http://schemas.datacontract.org/2004/07/Epic'.. Encountered 'Element' with name 'eNamedList', namespace ''.
So, my questions become:
How do I control serialization of my eString, or any IEnumerable<char> and always serialize as a string?
Why, when the element names match, do I get a failure on deserialization? (Am I just missing a namespace declaration?)
Thanks!
Update #1:
So, I removed the IEnumerable<char> interface from my eString, and just left the IEnumerable<char>.GetEnumerator() method, which allows my string to be used AS an IEnumerable<char> while in a foreach loop, but serializes as a string. #WIN
Also, thanks to dbc, updated the original post with the XML Deserializer (rather than DataContract Serializer) and deserialization works.
To answer your questions:
You probably shouldn't reinvent the wheel with custom string solutions. Regardless, if you want an (insanely) high-level of control over your (de-)serialization, you could implement IXmlSerializable and do the exact same thing yourself.
[XmlRoot("string-wrapper")]
public class CustomString : IXmlSerializable
{
public string Value { get; set; }
public XmlSchema GetSchema()
{
return null; // GetSchema should not be used.
}
public void ReadXml(XmlReader reader)
{
reader.MoveToContent();
bool isEmpty = reader.IsEmptyElement;
reader.ReadStartElement();
if (!isEmpty)
{
Value = reader.ReadString();
reader.ReadEndElement();
}
}
public void WriteXml(XmlWriter writer)
{
writer.WriteString(Value);
}
}
Serialization of a CustomString now yields <string-wrapper>Testing</string-wrapper>. I'll post some test code at the end of this post.
Your deserialization is likely broken because the XmlSerializer doesn't know that the IEnumerable you marked serializable should actually be treated like a string.
And now... Forget what I just told you. Unless you have very specific formatting requirements you should not implement your own version of a string. The built-in formatter knows a lot more formatting tricks (http://www.w3.org/TR/xmlschema-2/#built-in-datatypes), so you should probably let it do it's job.
Serializing classes is where the attributes come in, though I recommend you switch to the WFC data contracts, which may sound scary at first but actually provides a whole lot more for a lot less code. Again, I'm not sure what you're trying to accomplish, but trust me you don't want to get into the habit of hand writing XML.
If you're up for it you might like dynamic objects and the ExpandoObject (http://www.codeproject.com/Tips/227139/Converting-XML-to-an-dynamic-object-using-ExpandoO). These eliminate types all together and allow you to create dictionaries, arrays, named properties, whatever, all on the fly!
Finally, easy on the generics! Deserializing generic classes is not a trivial task. Besides, you probably don't need to. If you want your own collections, try the System.Collections.ObjectModel namespace. You don't have to worry about maintaining lists and implementing interfaces, just what you're actually storing:
class DictionaryOfStringsAndObjects : KeyedCollection<string, object {...}
class CollectionOfStrings : Collection<string> {...}
Also, try to avoid partial classes unless an ORM or a large legacy class forces it on you. You shouldn't actually use them unless you're made to.
All the best, and to a future devoid of XML!
public class CustomSerializer
{
public static void Test()
{
var obj = new CustomString {Value = "Random string!"};
var serializer = new CustomSerializer();
var xml = serializer.Serialize(obj);
Console.WriteLine(xml);
var obj2 = serializer.Deserialize<CustomString>(xml);
}
public string Serialize(object obj)
{
var serializer = new XmlSerializer(obj.GetType());
using (var io = new StringWriter())
{
serializer.Serialize(io, obj);
return io.ToString();
}
}
public T Deserialize<T>(string xml)
{
var serializer = new XmlSerializer(typeof (T));
using (var io = new StringReader(xml))
{
return (T)serializer.Deserialize(io);
}
}
}

How to prevent object to be serialize in XML

IDE: VS, C# .net 4.0, winforms
With the help of XMLSerializer I am able to generate XML of C# object, but I want to remove specific objects.
Is there any way to prevent specific objects to prevent in XML..?
using (MemoryStream xmlStream = new MemoryStream())
{
/*
XmlSerializer.Serialize Method (XmlWriter, Object)
Serializes the specified Object and writes the XML document to a file using the specified xmlwriter
Parameters
xmlWriter-
Type: System.Xml.XmlWriter
The XmlWriter used to write the XML document.
Type: System.Object
The Object to serialize.
*/
xmlSerializer.Serialize(xmlStream, YourClassObject);
xmlStream.Position = 0;
//Loads the XML document from the specified string.
xmlDoc.Load(xmlStream);
string fileName = YourClassObject.GetType().Name;
xmlDoc.Save("C:\\Users\\Yogesh\\Desktop\\Yardz_XMLS\\" + fileName + ".xml");
return xmlDoc.InnerXml;
Is there any way to prevent some properties to be serialize..?
Put XmlIgnore attribute on properties that you don't what to be serialized:
public class YourClass
{
public string Serailized { get; set; }
[XmlIgnore]
public string NotSerialized { get; set; }
}
See "Controlling XML Serialization Using Attributes" for more information.

entity framework serialize [duplicate]

This question already has answers here:
Circular reference detected exception while serializing object to JSON
(9 answers)
Closed 9 years ago.
I'm having trouble making an client-server app.
I'm working with Entity Framework(EF) and I need to serialize an object to send it via sockets that contains List attributes.
I'm using XMLSerialization for the Serialization part.
My problem is: When I try to Serialize a new Survey object and the OPTIONs List is Empty I can Serialize the object SURVEY. But, when I add an OPTION object to the SURVEY.OPTIONS list I cannot Serialize the object.
One of the classes that EF auto-generates from the Entity-Relationship Diagram is:
public partial class SURVEY
{
public SURVEY()
{
this.OPCIONs = new List<OPTION>();
}
public int id_survey { get; set; }
public System.DateTime initial_date { get; set; }
public System.DateTime end_date { get; set; }
public virtual List<OPTION> OPTIONs { get; set; }
}
I'm using this Code for get a Survey from the Database:
DateTime actualDate = new DateTime().Today;
private static ComedorCaniaDBContext context = new ComedorCaniaDBContext();
Survey survey = context.SURVEYs.Create()
survey = (SURVEY)context.SURVEYs
.Include("Options")
.Where(e => e.initial_date < actualDate && e.end_date > actualDate)
.FirstOrDefault();
I'm using this Code for Serialization:
public static Byte[] ObjectToByteArray<T>(T obj)
{
try
{
using (MemoryStream ms = new MemoryStream())
{
XmlSerializer xmlS = new XmlSerializer(typeof(T));
xmlS.Serialize(ms, obj);
return ms.ToArray();
}
}
catch
{
return null;
}
}
I'll appreciate your help.
Thanks.
Entity Framework is near impossible to make work with the built-in XML serializer and BinaryFormatter serializer, if you don't want to lose features like lazy loading. They just aren't made to deal with that.
You're going to have to use a different serializer that can handle Entity Framework objects, such as JSON.Net, or else write your own serializer.
See the following articles for the long line of others who have had the same question:
Circular reference detected exception while serializing object to JSON
How did I solve the Json serializing circular reference error?
Basically, you either get to keep lazy loading and use some other serializer or lose it and continue to use the built-in serializer.

How would I deserialize some class from XML (file), and vice versa?

I have the following class and data members (plus irrelevant methods) I am new to XML and .NET (that excuse is getting old though) and have spent a couple of days reading the MSDN entries (and whatever google turned up) for first XMLReader, then XMLDocument and now XDocument, XElement and XNode but am no closer to a concrete solution to serializing my class (perhaps I need to study serialization in .NET in more depth). To get me started I have some data in an XML file that I want to read (although it prolly is in the wrong format) in to initialize a class to initialize my application. The configuration class is as follows:
class IWantToFile
{
class DirsAndFiles
{
public List<string> Suffixes;
public string Dir;
}
enum OPOptsEnum
{
op1Description, op2Description, op3Description, op4Description,
op5Description, op6Description, op7Description, op8Description,
};
List<DirsAndFiles> ProjectDirs;
bool[] OPOpts = new bool[(int)OPOptsEnum.op8Description + 1];
bool otherOpt;
}
Observing the one to one and one to many relationships therein (eg List<DirsAndFiles> ProjectDirs) can someone please give concise methods to read and write this data to a file? It would greatly assist my development in these fields.
I've got as far as:
if (File.Exists(SPECFILENAME)) {
XDocument xdoc = XDocument.Load(SPECFILENAME);
//Ummm.....
}
but then my lack of .NET XML and Linq exeperience fail me.
I think you might want to use the XmlSerializer, which 'Serializes and deserializes objects into and from XML documents'?
See How to serialize an object to XML by using Visual C# for sample code.
[Serializable]
public class MyObject
{
public string SerializeMe { get; set; }
[XmlIgnore]
public string DONTSerializeMe { get; set; }
}
Helper....
public static class SerializerHelper<T>
{
public static string Serialize(T myobject)
{
XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
StringWriter stringWriter = new StringWriter();
xmlSerializer.Serialize(stringWriter, myobject);
string xml = stringWriter.ToString();
return xml;
}
public static T Deserialize(string xml)
{
XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
StringReader stringReader = new StringReader(xml);
return (T)xmlSerializer.Deserialize(stringReader);
}
}
Usage
MyObject myObject = new MyObject();
string xml = SerializerHelper<MyObject>.Serialize(myObject);
MyObject DeserializedObject = SerializerHelper<MyObject>.Deserialize(xml);

Categories