Ignoring a property during deserialization - c#

I have a class that is serializing very nicely - finally!
Now I want to add a property to this class, that I don't want to be serialized at all.
Is it possible to add this new property with some kind of attribute so that when I call serialize or deserialize methods, this property will go unnoticed?

[XmlIgnore]
public int DoNotSerialize { get { ... } set { ... } }

I think your looking for [XmlIgnore] attribute

Related

Control the XML generated for automatic properties

Can anyone explain how to control the XML generated ?
I have a simple test class, NumberService ...
[Serializable]
public class NumberService
{
public int Number1 { get; set; }
public int Number2 { get; set; }
}
Now if I use an XmlSerializer to deserialise an instance, I get what I expected ...
<NumberService>
<Number1>23</Number1>
<Number2>45</Number2>
</NumberService>
but I was attempting to send this and Fiddler was showing ...
<NumberService>
<_x003C_Number1_x003E_k__BackingField>10</_x003C_Number1_x003E_k__BackingField>
<_x003C_Number2_x003E_k__BackingField>2</_x003C_Number2_x003E_k__BackingField>
</NumberService>
Poking around I've read that this is because of my use of automatic properties, and indeed if I changed to ...
public class NumberService
{
private int _number1;
public int Number1
{
get { return _number1; }
set { _number1 = value; }
}
public int Number2 { get; set; }
}
indeed the XML changes to ...
<NumberService>
<_number1>4</_number1>
<_x003C_Number2_x003E_k__BackingField>6</_x003C_Number2_x003E_k__BackingField>
</NumberService>
But of course I can't change _number1 to Number1 as it'd conflict with the property :-(
So how can you control the XML ?
... and a bit more reading ...
this is involving WCF data contracts
This has to do with how the DataContractSerializer handles items with the Serializable attribute applied.
When confronted with the Serializable attribute, the DataContractSerializer will defer to the semantics that you would expect when using the instance with an IFormatter implementation; in other words, it will serialize the underlying fields using the names of the fields as the keys to the data.
Because you are using auto-generated properties, what you are seeing is actually the names of the auto-generated fields that the compiler generates for you.
In order to get around this, you should apply the DataContract attribute to the class and the DataMember attribute to the properties (and you can control the name by specifying it in the attribute if you want it to differ from the property name).
You also have the option of not specifying the DataContract/DataMember attributes at all and using POCO DataContract serialization; this assumes you have a default parameterless constructor along with only serializing public properties/fields.
You should remove the [Serializable] attribute. It is not used by XML Serialization, and it is giving the wrong message to the Data Contract Serializer.
If you are using just XmlSerialization then you can use attributes from System.Xml.Serialization namespace to control Xml-Serialization for example XmlAttributeAttribute.
If you wand to use DataContractSerializer in your Wcf service, you need to mark your class with DataContract attribute and mark all properties with DataMember attribute.
IMHO DataContractSerializer is much more advanced, than old XmlSerialization

how to serialize some attribute in some condition

When using XML serialization to serialize a class, how to make some attribute be outputted conditionally. i.e. In some case, it output this attribute, in other cases, it does not.
You can create an additional property which is called MyPropertySpecified, which returns a boolean.
When this property returns true, the MyProperty property will be serialized. When it returns false, it will not be serialized.
Also, you'd want to decorate that property with the XmlIgnoreAttribute, so that this specific property is not serialized.
Example:
public class Person
{
public string Name
{
get;
set;
}
[XmlIgnore]
public bool NameSpecified
{
get { return Name != "secret"; }
}
}
While works and is a rather short solution, the propertyNameSpecified pattern has some drawbacks in my opinion (pollutes the interface of your class; relies on property names; introduces implicit behavior).
If you only need to implement a simple condition (e.g. don't serialize a default value), then the DefaultValue attribute is a better choice.
For example:
public class PurchaseOrder
{
[DefaultValue("2002")]
public string Year;
}
If Year has the value "2002", it will be omitted from the XML output.
You can use OnSerializingAttribute while serializing which allows us to invoke method before serialization. You can get more information about it here
Imho you would need to implement IXmlSerializable on the class and implement the WriteXml and ReadXml methods in such a way that they only write the attribute based upon the conditions you specify and can handle reading with or without that particular attribute present upon deserialization.
IXmlSerializable at Msdn

Programmatically set properties to exclude from serialization

Is it possible to programmatically set that you want to exclude a property from serialization?
Example:
When de-serializing, I want to load up an ID field
When serializing, I want to NOT output the ID field
I believe there are three options here:
Use XmlIgnore attribute. The downside is that you need to know in advance which properties you want the xmlserializer to ignore.
Implement the IXmlSerializable interface. This gives you complete control on the output of XML, but you need to implement the read/write methods yourself.
Implement the ICustomTypeDescriptor interface. I believe this will make your solution to work no matter what type of serialization you choose, but it is probably the lengthiest solution of all.
It depends on serialization type. Here full example for doing this with BinaryFormatter:
You may use OnDeserializedAttribute:
[Serializable]
class SerializableEntity
{
[OnDeserialized]
private void OnDeserialized()
{
id = RetrieveId();
}
private int RetrievId() {}
[NonSerialized]
private int id;
}
And there is another way to do this using IDeserializationCallback:
[Serializable]
class SerializableEntity: IDeserializationCallback
{
void IDeserializationCallback.OnDeserialization(Object sender)
{
id = RetrieveId();
}
private int RetrievId() {}
[NonSerialized]
private int id;
}
Also you may read great Jeffrey Richter's article about serialization: part 1 and part 2.
If you are serializing to XML, you can use XMLIgnore
As in:
class SomeClass
{
[XmlIgnore] int someID;
public string someString;
}
An old post, but I found ShouldSerialize pattern
http://msdn.microsoft.com/en-us/library/53b8022e%28VS.71%29.aspx That is really HELPFUL!!!
If you want to include field during serialization but ignore it during deserialization then you can use OnDeserializedAttribute to run a method which will set default value for ID field.
If you're using XML serialization, use the [XmlIgnore] attribute. Otherwise, how to ignore a particular property is defined by the serializer itself.
The NonSerializedAttribute attribute.
http://msdn.microsoft.com/en-us/library/system.nonserializedattribute.aspx

Is it necessary to declare attribute [DataMember(Order=n)] on public method?

In my solution, I have created public class to store value and already declare [DataContract/DataMember] attribute.
For example,
[DataContract]
public class MeterSizeInfo
{
string _meterSizeId;
[DataMember(Order = 1)]
public string MeterSizeId
{
get { return this._meterSizeId; }
set { this._meterSizeId = value; }
}
string _meterSizeName;
[DataMember(Order = 2)]
public string MeterSizeName
{
get { return this._meterSizeName; }
set { this._meterSizeName = value; }
}
}
Then I need to add another public method exposing to entire project.
I wonder I have to add [DataMember(Order = 3)] for it or not.
[DataMember(Order = 3)] //<--- must declare or not?
public string DoSomething()
{
// do something...
}
I understand that if I want to use serializer in protobuf-net to serialize my data stored in, I have to declare those attribute. but I'm not sure about that on method.
please help.
Thank you in advance.
protobuf-net is a value serializer; it doesn't know anything about methods, except for properties. If you use the same (or compatible) type, then the method will be present automatically, but this is nothing to do with protobuf-net (or any other serialization).
Re the topic of adding attributes; with the current release it generally needs something to know which properties to serialize (and more importantly: with what identifiers). There is an implicit mode, but I don't recommend it unless you know you aren't going to be ever changing the type again. Ever. At all.
In "v2", you can remove the attributes; you have the option of using an external model for this, so you might have:
var model = TypeModel.Create();
model[typeof(MeterSizeInfo)].Add("MeterSizeId", "MeterSizeName");
(don't quote me on the exact API, but something like that)
You can then use model.Serialize etc
No - shouldn't be there. You can't serialise a method!
No only properties are readable and writable in that way... so you can't add the attribute for a method.

Including arrary index in XML Serialization

I have a class that looks like this
public class SomeClass
{
public SomeChildClass[] childArray;
}
which will output XML from the XMLSerializer like this:
<SomeClass>
<SomeChildClass>
...
</SomeChildClass>
<SomeChildClass>
...
</SomeChildClass>
</SomeClass>
But I want the XML to look like this:
<SomeClass>
<SomeChildClass index=1>
...
</SomeChildClass>
<SomeChildClass index=2>
...
</SomeChildClass>
</SomeClass>
Where the index attribute is equal to the items position in the array.
I could add an index property to SomeChildClass with the "XMLAttribute" attribute but then I would have to remember to loop through the array and set that value before I serialize my object.
Is there some attribute i can add or some other way to automatically generate the index attribute for me?
The best approach would be to do what you said and add a property to the "SomeChildClass" like this
[XmlAttribute("Index")]
public int Order
{ { get; set; } }
Then however you are adding these items to your array, make sure that this property get's set. Then when you serialize....Presto!
You may need to look into implementing System.Xml.Serialization.IXmlSerializable to accomplish this.
You can check XmlAttributeOverrides Class.

Categories

Resources