C#: [NonSerialized] при реализации ISerializable

Я не понимаю использование [NonSerialized] атрибут при реализации ISerializable на уроке. Я посещал курс "Программирование на C#" (Microsoft 20-483), и он используется в нескольких примерах, но не в деталях.
Возьмите этот класс:

[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);
    }
}

Я прокомментировал, что я ожидаю: _Age это частное поле, которое я не хочу сериализовать. Я специально написала в GetObjectData сериализовать это. Это любопытно, но я хотел понять, как [NonSerialized] будет обработан.
Если я запускаю что-то подобное в 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);
        }
    }
}

Возраст есть... В файле, где находится сериализованный объект, и в регидратированном объекте. Мой вопрос: почему? Какая польза от [NonSerialized] атрибут в этом случае, так как мы просто не должны добавлять Age в GetObjectData метод? Я явно что-то упускаю, но не могу понять, что. Спасибо!

Изменить: пример, который присутствует в курсе:

[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);
    }
}

1 ответ

Решение

Итак, я нашел что-то интересное на сайте Microsoft:
https://docs.microsoft.com/en-us/dotnet/api/system.nonserializedattribute?view=netframework-4.7

Целевые объекты для атрибута NonSerializedAttribute являются открытыми и закрытыми полями сериализуемого класса. По умолчанию классы не сериализуются, если они не помечены как SerializableAttribute. В процессе сериализации все открытые и закрытые поля класса сериализуются по умолчанию. Поля, помеченные как NonSerializedAttribute, исключаются при сериализации. Если вы используете класс XmlSerializer для сериализации объекта, используйте класс XmlIgnoreAttribute для получения той же функциональности. В качестве альтернативы, реализуйте интерфейс ISerializable для явного управления процессом сериализации. Обратите внимание, что классы, реализующие ISerializable, должны быть помечены как SerializableAttribute.

Так что, в основном, поэтому я не понял, как использовать [NonSerialized] при реализации ISerializable: они не предназначены для совместной работы.

Другие вопросы по тегам