NonSerialized dind't work - c#

i'm serialization a class but i can't exclude some field in my class.
[Serializable]
public class DicData
{
private GDicJson DeserializedGDicJson = new GDicJson();
public UOCDicData BuiltDicData;
[NonSerialized]
public string CacheName = "";
}
in my expection, a public field CacheName didn't include in my *.xml deserialized output, but it included in .xml file.
here are serializing rutine.
XmlSerializer myXml = new XmlSerializer(typeof(DicData), "test");
myXml.Serialize(myFile, this); //note:a serializing perform in method of himself.

For XmlSerializer you want
[XmlIgnore]
Also, note that the [Serializable] is unnecessary in this case.
As a final note: public fields are not encouraged; properties are almos always preferred. The addition of {get;set;} would go a long way...

Related

Serialize an object to XML without using attributes

Is it possible to control XmlSerializer/DataContractSerializer behavior without specifying any serialization attributes?
To be more specific, I want to control the serialization (XmlIgnore, custom attribute name etc.), but without decorating my properties.
Use cases:
A large existing class, which I don't wish to pollute with serialization attributes
Serializing a class for which no source code is available
Switching from using XmlSerializer to DataContractSerializer to JSON without changing class code
For example, how would I serialize the following without uncommenting the attributes:
// [Serializable]
public MyClass
{
// [XmlIgnore] - The following property should not be serialized, without uncommenting this line
public int DontSerializeMeEvenThoughImPublic { get; set; }
// [XmlAttribute("another_name")] - should be serialized as 'another_name', not 'SerializeMeAsXmlAttribute'
public double SerializeMeAsXmlAttribute { get; set; }
// [DataMember] - should be included
private string IWantToBeSerializedButDontDecorateMeWithDataMember { get; set; }
}
You can't (do it elegantly).
The only way to modify the way the XmlSerializer serializes classes is by using attributes (by the way SerializableAttribute is not required). The DataContractSerializer is even worse.
One possible solution is to create intermediate classes for XML serialization/desrialization and use Automapper to copy the data between the "real" class and mediator.
I've used this approach to keep the front end XML serialization concerns outside of my business logic data types.
I know this is an old question, but for the XmlSerializer part, it's interesting that no one has suggested the use of Attribute overrides.
Although not solving the Private property, but AFAIK you can't do that with attributes either, so the only route there would be the IXmlSerializable interface.
But what you can do by adding Attributes should be possible with overrides as well.
The following should work for the change wishes reflected by the outcommented XmlAttributes:
public class Program
{
public static void Main()
{
XmlAttributeOverrides overrides = new XmlAttributeOverrides();
overrides.Add(typeof(MyClass), "DontSerializeMeEvenThoughImPublic", new XmlAttributes { XmlIgnore = true });
overrides.Add(typeof(MyClass), "SerializeMeAsXmlAttribute", new XmlAttributes { XmlAttribute = new XmlAttributeAttribute("another_name") });
XmlSerializer serializer = new XmlSerializer(typeof(MyClass), overrides);
using (var writer = new StringWriter())
{
serializer.Serialize(writer, new MyClass());
Console.WriteLine(writer.ToString());
}
}
}
Serialization via XmlSerializer should work without the attributes.

Serialize DateTime property to XML in C#

I´m a programming student and I would like to know if it is possible to change the format of a date when I serialize it in a xml file. This date is an attribute of an ObservableCollection of objects "Loan", this objects have two DateTime properties, one of the dates is a nullable object. I serialize all the collection including the date.
I would like to obtain in the xml file:
<OutDate> 15-03-2014 </OutDate>
<!--If the date is null I don´t want to appear the node-->
And I´m getting this:
<OutDate>2014-03-15T00:00:00</OutDate>
<InDate xsi:nil="true" />
This is part of my code project:
Part of my class Loan, already mark as serializable, looks like this:
private string isbn;
private string dni;
private DateTime dateOut;
private DateTime? dateIn;
// Setters and Gettters and constructors
This is the method for serialize:
// I will pass three collections to this method loans, books and clients
public void SerializeToXML<T>(string file, string node, ObservableCollection<T> collection)
{
XmlRootAttribute root = new XmlRootAttribute(node);
XmlSerializer serializer = new XmlSerializer(typeof(ObservableCollection<T>), root);
using (FileStream fs = new FileStream(file, FileMode.Create))
{
serializer.Serialize(fs, collection);
}
}
The call:
SerializeToXML<Loan>(_file, "Library", manager.LoansCollection);
Thnks.
If you don't want to implement IXmlSerializable, some DateTime to string conversion of a backing field should do the trick, something like this:
public class Loan
{
[XmlIgnore]
private DateTime _dateOut;
public string OutDate
{
get { return _dateOut.ToString("dd-MM-yyyy"); }
set { _dateOut = DateTime.Parse(value); }
}
}
Probably the simplest way to achieve this is to implement the IXmlSerializable interface on your class instead. Something along the following lines
public class Loan : IXmlSerializable
{
public void WriteXml(XmlWriter writer)
{
if(dateIn.HasValue)
{
writer.WriteElementString("dateIn", dateIn.Value.ToString());
}
}
}
On the read you'll need to read the Element name, if it's dateIn set that, otherwise set the appropriate value. Basically checking to see if it exists in the XML.
Have a look at the XmlElement attribute class (in System.Xml.Serialization). If that doesn't work then this answer shows how to use a proxy property
[XmlElement("TheDate", DataType = "date")]
public DateTime TheDate { get; set; }
I know it's late to get my answer marked as "the one", but you can have control over serialization without implementing complex interfaces or wrapping stuff as a workaround.
public DateTime? InDate { get; set }
public bool ShouldSerializeInDate()
{
return InDate.HasValue;
}
The C# XML Serializer has a not so well documented functionality. Every public property can have a method for turning on or off the serialization of the property. The method has to be called: ShouldSerializeXYZ where XYZ is the exact name of the property that you want to control.
See:
Xml serialization - Hide null values

C# XML serialization preserve list<T> order

Currently I'm making a kind of History log using a List. I'm saving this list by simply serializing it with the XML serializer, however whenever I serialize the list and then deserialize it, the order is different to when I first created the list.
For example, when I first create the list, it may be in this order
A
B
C
Yet when I serialize/deserialize it may become something like
B
C
A
Is there a way or forcing the serializer to preserve the order of the list when serializing? (I've found it actually saves it in the wrong order to begin with)
Current Code:
public static List<StoredData> clipboardData = new List<StoredData>();
private void SaveClipboard()
{
XmlSerializer serializer = new XmlSerializer(typeof(List<StoredData>));
using (StreamWriter stream = new StreamWriter(historyFile))
{
serializer.Serialize(stream, clipboardData);
}
Console.WriteLine("Saved");
}
StoredData Class
[Serializable]
public class StoredData
{
public String storedClip;
public DateTime storedTime;
}
Here is a way to preserve the order when serializing your XML
[Serializable]
public class StoredData
{
[Datamember(Name = "Clip", Order = 1)]
public String storedClip;
[Datamember(Name = "Time", Order = 2)]
public DateTime storedTime;
}

How to serialize class members as attributes to xml in C#

I am trying to serialize my object to xml. A serializer seemingly serializes all data members as children, but I want to serialize all members as attributes, not children.
Here's a code example:
[DataContract]
public class MyDataClass
{
[DataMember]
int foo = 24;
[DataMember]
string bar = "brabrabra";
}
This will be serialized as following xml when I use DataContractSerializer:
<MyDataClass xmlns="..." xmlns:i="...">
<foo>24</foo>
<bar>brabrabra</bar>
</MyDataClass>
However, I want to serialize it as following xml somehow:
<MyDataClass xmlns="..." xmlns:i="..." foo="24" bar="brabrabra" />
Is there any way to serialize like that? Or, should I write my own serializer to realize it?
For reference, I am using DataContract serializer in this sample, but I can change it to a normal XmlSerializer or another one if there's a better one.
Hope someone knows about this.
Aki
Have a look at XMLAttribute. Only works with XMLSerializer though.
You can use a simple XmlSerializer to achieve this, in the following way:
[Serializable]
public class SerializationTest2
{
[XmlAttributeAttribute]
public string MemberA { get; set; }
}
[Test]
public void TestSerialization()
{
var d2 = new SerializationTest2();
d2.MemberA = "test";
new XmlSerializer(typeof(SerializationTest2))
.Serialize(File.OpenWrite(#"c:\temp\ser2.xml"), d2);
}
Put [XmlAttribute] before foo and bar declaration.
Great ref: http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlserializer.aspx

Public fields/properties of a class derived from BindingList<T> wont serialize

I'm trying to serialize a class that derives from BindingList(Floor), where Floor is a simple class that only contains a property Floor.Height
Here's a simplified version of my class
[Serializable]
[XmlRoot(ElementName = "CustomBindingList")]
public class CustomBindingList:BindingList<Floor>
{
[XmlAttribute("publicField")]
public string publicField;
private string privateField;
[XmlAttribute("PublicProperty")]
public string PublicProperty
{
get { return privateField; }
set { privateField = value; }
}
}
I'll serialize an instance of CustomBindingList using the following code.
XmlSerializer ser = new XmlSerializer(typeof(CustomBindingList));
StringWriter sw = new StringWriter();
CustomBindingList cLIst = new CustomBindingList();
Floor fl;
fl = new Floor();
fl.Height = 10;
cLIst.Add(fl);
fl = new Floor();
fl.Height = 10;
cLIst.Add(fl);
fl = new Floor();
fl.Height = 10;
cLIst.Add(fl);
ser.Serialize(sw, cLIst);
string testString = sw.ToString();
Yet testString above ends getting set to the following XML:
<CustomBindingList xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">
<Floor Height="10" />
<Floor Height="10" />
<Floor Height="10" />
</CustomBindingList>"
How do I get "publicField" or "publicProperty to serialize as well?
The short answer here is that .NET generally expects something to be a collection xor to have properties. This manifests in a couple of places:
xml serialization; properties of collections aren't serialized
data-binding; you can't data-bind to properties on collections, as it implicitly takes you to the first item instead
In the case of xml serialization, it makes sense if you consider that it might just be a SomeType[] at the client... where would the extra data go?
The common solution is to encapsulate a collection - i.e. rather than
public class MyType : List<MyItemType> // or BindingList<...>
{
public string Name {get;set;}
}
public class MyType
{
public string Name {get;set;}
public List<MyItemType> Items {get;set;} // or BindingList<...>
}
Normally I wouldn't have a set on a collection property, but XmlSerializer demands it...
XML serialization handles collections in a specific way, and never serializes the fields or properties of the collection, only the items.
You could either :
implement IXmlSerializable to generate and parse the XML yourself (but it's a lot of work)
wrap your BindingList in another class, in which you declare your custom fields (as suggested by speps)
This is known issue with XML serialization and inheriting from collections.
You can read more info on this here : http://social.msdn.microsoft.com/Forums/en-US/asmxandxml/thread/0d94c4f8-767a-4d0f-8c95-f4797cd0ab8e
You could try something like this :
[Serializable]
[XmlRoot]
public class CustomBindingList
{
[XmlAttribute]
public string publicField;
private string privateField;
[XmlAttribute]
public string PublicProperty
{
get { return privateField; }
set { privateField = value; }
}
[XmlElement]
public BindingList<Floor> Floors = new BindingList<Floor>();
}
This means you can add floors by using Floors.Add and you will get the result you want, I hope, however, I didn't try it. Keep in mind that playing around with attributes is the key to XML serialization.

Categories

Resources