什么是[可序列化],什么时候应该使用它?


Answers:


369

它是什么?

在.Net Framework应用程序中创建对象时,无需考虑数据如何存储在内存中。因为.Net Framework为您解决了这一问题。但是,如果要将对象的内容存储到文件,将对象发送到另一个进程或通过网络传输它,则必须考虑对象的表示方式,因为您需要转换为其他格式。这种转换称为SERIALIZATION。

用于序列化

序列化允许开发人员保存对象的状态并根据需要重新创建它,从而提供对象的存储以及数据交换。通过序列化,开发人员可以执行一些操作,例如通过Web服务将对象发送到远程应用程序,将对象从一个域传递到另一个域,将对象作为XML字符串通过防火墙传递,或者维护安全性或特定于用户的行为。跨应用程序的信息。

应用于SerializableAttribute一种类型,以指示可以序列化此类型的实例。应用SerializableAttribute即使类还实现了ISerializable控制序列化过程的界面。

SerializableAttribute默认情况下,将序列化由标记的类型中的所有公共字段和私有字段,除非该类型实现ISerializable接口以覆盖序列化过程。默认的序列化过程不包括标有的字段NonSerializedAttribute。如果可序列化类型的字段包含特定于特定环境的指针,句柄或某些其他数据结构,并且无法在其他环境中有意义地重构,则您可能希望将其应用于NonSerializedAttribute该字段。

有关更多详细信息,请参见MSDN

编辑1

任何不将某些内容标记为可序列化的原因

传输或保存数据时,只需要发送或保存所需的数据。因此,将减少传输延迟和存储问题。因此,您可以在序列化时选择不必要的数据块。


1
@dwbartz您的问题在这里得到答案 链接
jayasurya_j

2
很好的爆炸效果,很高兴将其添加到MSDN中的属性=)
Martea

@jayasurya_j很可惜,被接受的答案并没有太多谈论私有部分
亚历山大

1
好的解释
Zakir HC

42

[Serializable]属性的一些实际用途:

  • 使用二进制序列化保存对象状态;您可以非常容易地将应用程序中的整个对象实例“保存”到文件或网络流,然后通过反序列化来重新创建它们- BinaryFormatter在System.Runtime.Serialization.Formatters.Binary中检出类
  • 可以使用Clipboard.SetData()-不可序列化的类将其对象实例可以存储在剪贴板上的编写类放在剪贴板上。
  • 编写与.NET Remoting兼容的类;通常,您在应用程序域之间传递的任何类实例(从扩展的域实例除外MarshalByRefObject)必须是可序列化的。

这些是我遇到的最常见的用例。


41

由于最初的问题与SerializableAttribute有关,因此应注意,此属性仅在使用BinaryFormatter或SoapFormatter时适用。

除非您真的非常注意细节,何时使用它以及它的实际用途,否则这将使您感到困惑。

它与XML或JSON序列化无关。

与SerializableAttribute一起使用的是ISerializable接口和SerializationInfo类。这些也仅与BinaryFormatter或SoapFormatter一起使用。

除非您打算使用Binary或Soap序列化您的类,否则请勿将您的类标记为[Serializable]。XML和JSON序列化程序甚至都不知道它的存在。


16
“它与XML或JSON序列化无关”-谢谢!最后,一个解释为何我可以愉快地将任何类序列化为具有或不具有此属性的XML
userSteve

1
你有这个来源吗?
Michiel van Oosterhout

“ XML和JSON序列化程序甚至都不知道它的存在”。我不知道 当我通过WCF JSON格式化一个类时,如果该类为Serializable,则属性名称前面带有一个下划线,并且在删除属性时没有。因此可能会有一些干扰。
詹斯

@Jens如果我正确理解JSON.net一点也不在乎,但是asp.net会稍微改变这种行为。我相信您可以使用JsonObject / JsonProperty属性来规避此问题。
基地

29

序列化是将对象转换为字节流以存储对象或将其传输到内存,数据库或文件的过程。

序列化的工作方式

此图显示了序列化的整个过程。

在此处输入图片说明

对象被序列化为流,该流不仅携带数据,还携带有关对象类型的信息,例如其版本,区域性和程序集名称。通过该流,可以将其存储在数据库,文件或内存中。

msdn中的详细信息。



14

序列化

序列化是将一个对象或一组对象图转换为流的过程,对于二进制序列化,它是一个字节数组

序列化的用途

  1. 将对象的状态保存到文件,数据库等中并在以后使用。
  2. 将对象从一个进程发送到同一台计算机上的另一个进程(应用程序域),并通过电线将其发送到另一台计算机上运行的进程。
  3. 在处理主对象时创建原始对象的克隆作为备份。
  4. 一组对象可以轻松地复制到系统的剪贴板中,然后粘贴到相同或另一个应用程序中

以下是在对象序列化期间使用的一些有用的自定义属性

[Serializable] ->当我们标记对象的可序列化时使用 [NonSerialized] ->当我们不想序列化对象的字段时使用。 [OnSerializing] ->在序列化对象时要执行某些操作时使用 [OnSerialized] ->在将对象序列化为流后要执行某些操作时使用。

以下是序列化的示例

[Serializable]
    internal class DemoForSerializable
    {
        internal string Fname = string.Empty;
        internal string Lname = string.Empty;

        internal Stream SerializeToMS(DemoForSerializable demo)
        {
            DemoForSerializable objSer = new DemoForSerializable();
            MemoryStream ms = new MemoryStream();
            BinaryFormatter bf = new BinaryFormatter();
            bf.Serialize(ms, objSer);
            return ms;
        }

        [OnSerializing]
        private void OnSerializing(StreamingContext context) {
            Fname = "sheo";
            Lname = "Dayal";
        }
        [OnSerialized]
        private void OnSerialized(StreamingContext context)
        {
       // Do some work after serialized object
        }

    }

这是调用代码

class Program
    {
        string fname = string.Empty;
        string Lname = string.Empty; 

       static void Main(string[] args)
        {
            DemoForSerializable demo = new DemoForSerializable();

            Stream ms = demo.SerializeToMS(demo);
            ms.Position = 0;

            DemoForSerializable demo1 = new BinaryFormatter().Deserialize(ms) as DemoForSerializable;

            Console.WriteLine(demo1.Fname);
            Console.WriteLine(demo1.Lname);
            Console.ReadLine();
        }

    }
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.