C# 序列化

可远程处理和不可远程处理的对象

请记住,在一个应用程序域中创建并因而特定于该域的对象可以直接从该域中调用,但如果要从该域中调用在其他域中创建的对象,就必须先进行一些设置,这一点非常重要。并非所有类型的对象都可以跨域边界进行有效地发布和使用;因此,必须根据应用程序的要求来决定要发布哪种对象。为了开发分布式应用程序,有两类对象可供选择:不可远程处理的对象和可远程处理的对象。

不可远程处理的对象

有些对象不能离开它们的应用程序域;这些对象未声明序列化方法,因而永远得不到封送处理。这些不可远程处理的对象专门在创建它们的应用程序域中使用,并始终直接从该应用程序域进行访问。.NET Framework类库中的大多数基类都属于不可远程处理的对象。不可远程处理的对象不能在其他应用程序域中进行复制或表示。这些对象只能从它们的原始应用程序域进行访问。

可远程处理的对象

可远程处理的对象能够从其应用程序域或使用代理的上下文之外进行访问,您也可以复制它们并在其应用程序域或上下文之外传递其副本;这意味着,有些可远程处理的对象将通过引用进行传递,有些则将通过值传递。

可远程处理的对象是能够在大范围分布式环境中正常运行的对象。它们主要有两种类型:

·        按值封送对象,这种对象将从应用程序域中进行复制和传递。

·        引用封送对象,将为这种对象创建代理,而客户端则使用代理远程访问这些对象。(eg.Activator.getobject(Typetype,stringurl) :为指定类型和url所指示的已知对象(泛型T)创建一个代理..其中第一个参数是远程对象的类型。第二个参数就是服务器端的uri)

按值封送对象

按值封送 (MBV)对象声明其序列化规则(通过实现ISerializable来实现其自己的序列化,或者通过用SerializableAttribute标记以指示系统自动序列化该对象),但不扩展MarshalByRefObject。远程处理系统会创建这些对象的完整副本,并将该副本传递给调用应用程序域。当该副本到达调用方的应用程序域中时,对该副本的调用将直接转到该副本。另外,以参数形式传递的 MBV 对象还将按值传递。除了声明SerializableAttribute属性或实现ISerializable外,您无需执行任何操作即可跨应用程序或上下文边界按值传递类的实例

引用封送对象

引用封送 (MBR)对象是至少扩展了 System.MarshalByRefObject 的可远程处理对象。根据已声明的激活类型,当客户端在其自己的应用程序域中创建 MBR 对象的实例后,.NET远程处理结构将创建表示该 MBR对象的代理,并向调用方返回对该代理的引用。随后,客户端将调用该代理。.NET远程处理会将这些调用封送给远程对象所在的应用程序域,从而实现迭代调用。

系列化

序列化是将对象处理为字节流以存储对象或传输到内存、数据库或文件。其主要目的是保存对象的状态,以便可以在需要时重新创建对象。相反的过程称为反序列化。

序列化的工作方式:


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

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

序列化一个对象

为了序列化一个对象,我们需要一个被序列化的对象,一个容纳被序列化了的对象的(字节)流和一个格式化器。进行序列化之前我们先看看System.Runtime.Serialization名字空间。ISerializable接口允许我们使任何类成为可序列化的类

如果我们给自己写的类标识[Serializable]特性,我们就能将这些类序列化。除非类的成员标记了[NonSerializable],序列化会将类中的所有成员都序列化

用于序列化

通过序列化,开发人员可以保存对象的状态,并在需要时重新创建该对象,从而提供对象的存储以及数据交换。通过序列化,开发人员还可以执行类似如下的操作:通过 Web服务将对象发送到远程应用程序、将对象从一个域传递到另一个域、以 XML字符串的形式跨防火墙传递对象,或者跨应用程序维护安全信息或用户特定信息。

序列化的类型

1.  二进制(流)序列化

2.  SOAP序列化

3. XML序列化

二进制序列化和 XML 序列化

在二进制序列化中,会序列化所有成员(甚至包括那些只读成员),从而可以提高性能。

XML 序列化提供了可读性更好的代码,并在对象共享和使用方面提供了更大的灵活性,以便实现互操作性。

二进制序列化

二进制序列化使用二进制编码来生成精简的序列化,以用于存储或基于套接字的网络流等。

XML 序列化

XML 序列化将对象的公共字段和属性或者方法的参数及返回值序列化为符合特定 XML架构定义语言(XSD)文档的 XML流。XML 序列化会生成具有转换为 XML的公共属性和字段的强类型类。 System.Xml.Serialization 包含序列化和反序列化XML所需的类。

您可以将特性应用于类和类成员,以控制 XmlSerializer 序列化或反序列化类实例的方式。

SOAP 序列化

XML 序列化还可用于将对象序列化为符合 SOAP规范的 XML流。SOAP 是一种基于 XML的协议,它是专门为使用XML来传输过程调用而设计的。如同常规的 XML序列化,特性可用于控制XML Web services生成的文本样式的 SOAP消息。

实例:基本序列化

要使一个类可序列化,最简单的方法是使用 Serializable 属性对它进行标记,如下所示:

[Serializable]
public class MyObject {
   public int n1 = 0;
   public int n2 = 0;
   public String str = null;
}

之后此对对象就可跨应用程序调用了。。

以下代码片段说明了如何将此类的一个实例序列化为一个文件:

MyObject obj = new MyObject();
obj.n1 = 1;
obj.n2 = 24;
obj.str = "一些字符串";
IFormatter formatter = new BinaryFormatter();
Stream stream = new FileStream("MyFile.bin", FileMode.Create, FileAccess.Write, FileShare.None);
formatter.Serialize(stream, obj);
stream.Close();
View Code

本例使用二进制格式化程序进行序列化。您只需创建一个要使用的流(Stream)和格式化程序的实例(formatter),然后调用格式化程序的 Serialize 方法。流和要序列化的对象实例作为参数提供给此调用。类中的所有成员变量(甚至标记为 private 的变量)都将被序列化,但这一点在本例中未明确体现出来。在这一点上,二进制序列化不同于只序列化公共字段的 XML 序列化程序

将对象还原到它以前的状态也非常容易。首先,创建格式化程序和流以进行读取,然后让格式化程序对对象进行反序列化。以下代码片段说明了如何进行此操作。

IFormatter formatter = new BinaryFormatter();
Stream stream = new FileStream("MyFile.bin", FileMode.Open, 
FileAccess.Read, FileShare.Read);
MyObject obj = (MyObject) formatter.Deserialize(fromStream);
stream.Close();
// 下面是证明

Console.WriteLine("n1: {0}", obj.n1);
Console.WriteLine("n2: {0}", obj.n2);
Console.WriteLine("str: {0}", obj.str);
View Code

上面所使用的 BinaryFormatter 效率很高,能生成非常紧凑的字节流。所有使用此格式化程序序列化的对象也可使用它进行反序列化,对于序列化将在 .NET 平台上进行反序列化的对象,此格式化程序无疑是一个理想工具。

需要注意的是,对对象进行反序列化时并不调用构造函数。对反序列化添加这项约束,是出于性能方面的考虑。但是,这违反了对象编写者通常采用的一些运行时约定,因此,开发人员在将对象标记为可序列化时,应确保考虑了这一特殊约定。

JSON序列化

序列化后含有$id问题:这是因为 类有[DataContract(IsReference = true)] 标识导致。。

 

JObject 反序列化 

接口在使用动态类型Dynamic返回数据后,调用者得到的可能是Newtonsoft.Json.Linq.JObject 对象,可以用以下方法 反序列化为具体的对象。

// pick out one album
JObject jalbum = albums[0] as JObject;

// Copy to a static Album instance
Album album = jalbum.ToObject<Album>();
原文地址:https://www.cnblogs.com/peterYong/p/6556567.html