I dont' understand the use of the [NonSerialized]
attribute when implementing ISerializable
on a class. I attended the "programming in C#" (Microsoft 20-483) course and it's used in few examples, but not in details.
Take this class:
[Serializable]
public class TestNonSerializable : ISerializable
{
public string FirstName { get; set; }
public string LastName { get; set; }
[NonSerialized]
private int _Age;
public int Age
{
get { return this._Age; }
set { this._Age = value; }
}
public TestNonSerializable()
{ }
public TestNonSerializable(SerializationInfo info, StreamingContext context)
{
FirstName = info.GetValue("Name", typeof(string)) as string;
LastName = info.GetValue("LastName", typeof(string)) as string;
// I expect this to throw an exception because the value doesn't exists.
// But it exists!
Age = (int)info.GetValue("Age", typeof(int));
}
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("Name", FirstName);
info.AddValue("LastName", LastName);
// I expect this to be empty
info.AddValue("Age", Age);
}
}
I commented what I expect: _Age
is a private field that I don't want to serialize. I specifically written in GetObjectData
to serialize it. It's a curious thing to do, but I wanted to understand how [NonSerialized]
would be handled.
If I run something like this in the Main
:
class Program
{
static void Main(string[] args)
{
var myObject = new TestNonSerializable()
{
FirstName = "Foo",
LastName = "Bar",
Age = 32,
};
// Instanciate a SOAP formatter
IFormatter soapFormat = new SoapFormatter();
// Serialize to a file
using (FileStream buffer = File.Create(@"D:\temp\TestNonSerializable.txt"))
{
// In the file generated, I expect the age to be empty. But the value
// is set to 32
soapFormat.Serialize(buffer, myObject);
}
// Deserialize from a file
using (FileStream buffer = File.OpenRead(@"D:\temp\TestNonSerializable.txt"))
{
// The age is being deserialized
var hydratedObject = soapFormat.Deserialize(buffer);
}
}
}
The age is there... In the file where the serialized object is and in the rehydrated object. My question is: why? What's the use of the [NonSerialized]
attribute in this case since we just have to not add Age
in the GetObjectData
method?
I'm clearly missing something, but I can't figure what.
Thanks!
Edit: the example that is present in the course:
[Serializable]
public class ServiceConfiguration : ISerializable
{
[NonSerialized]
private Guid _internalId;
public string ConfigName { get; set; }
public string DatabaseHostName { get; set; }
public string ApplicationDataPath { get; set; }
public ServiceConfiguration()
{
}
public ServiceConfiguration(SerializationInfo info, StreamingContext ctxt)
{
this.ConfigName
= info.GetValue("ConfigName", typeof(string)).ToString();
this.DatabaseHostName
= info.GetValue("DatabaseHostName", typeof(string)).ToString();
this.ApplicationDataPath
= info.GetValue("ApplicationDataPath", typeof(string)).ToString();
}
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("ConfigName", this.ConfigName);
info.AddValue("DatabaseHostName", this.DatabaseHostName);
info.AddValue("ApplicationDataPath", this.ApplicationDataPath);
}
}
答案 0 :(得分:2)
好的,所以我在微软网站上发现了一些有趣的东西:
https://docs.microsoft.com/en-us/dotnet/api/system.nonserializedattribute?view=netframework-4.7
NonSerializedAttribute属性的目标对象是可序列化类的公共字段和私有字段。默认情况下,除非用SerializableAttribute标记,否则类不可序列化。在序列化过程中,默认情况下序列化类的所有公共和私有字段。标记为NonSerializedAttribute的字段在序列化期间被排除。如果您使用XmlSerializer类来序列化对象,请使用XmlIgnoreAttribute类来获取相同的功能。 或者,实现ISerializable接口以显式控制序列化过程。请注意,实现ISerializable的类仍必须使用SerializableAttribute标记。
所以,基本上,这就是为什么我在实施[NonSerialized]
时无法理解ISerializable
的使用:他们并不打算一起工作。