心海巨澜

天行键,君子以自强不息;地势坤,君子以厚德载物!

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

      IExtensibleDataObject,MSDN给出的解释为:提供一个数据结构,用于存储 XmlObjectSerializer 在反序列化一个用 DataContractAttribute 属性标记的类型期间遇到的额外数据。命名空间:  System.Runtime.Serialization,程序集:  System.Runtime.Serialization。

      IExtensibleDataObject 接口提供了单个属性,该属性设置或返回一个用于存储数据协定外部数据的结构。额外数据存储在 ExtensionDataObject 类的实例中,并且通过 ExtensionData 属性访问。在接收、处理和返回数据的往返操作中,额外数据被原封不动地返回到原始发送方。这可用于存储从协定的将来版本接收的数据。如果您没有实现该接口,则会在往返操作中忽略和丢弃任何额外数据。

      在WCF契约版本管理过程中,可以借用此接口,使传输的数据契约类继承此接口。IExtensibleDataObject对客户端的影响:在1.0版本的客户端上保存从2.0版本的服务端所获得的数据;确保在更新时能够包含原始的数据。对服务端的影响:保存从客户端获得的未知数据;用于支持其他调用了2.0版本的服务但仍需要1.0版本的服务进行实际处理的情况;会承担拒绝服务攻击和非必要的使用服务器资源的风险。

      IExtensibleDataObject主要是通过序列化方式与反序列化方式对WCF数据契约起作用:在序列化数据契约的时候,保存未知的元素;在反序列化的时候,多余的数据将被放入到一个字典中;在序列化过程中,相同的数据按照其原始提供的样子以XML的形式写入。

      下面我们通过一个DEMO来演示IExtensibleDataObject对数据契约的变化产生的影响:

      1、新建一个Console Application程序,删除自动添加的文件;

      2、新建Item.cs类,代码如下:

[DataContract(Name = "Item", Namespace = "http://schemas.xinhaijulan.com/demos/IExtensibleDataObjectApp")]
public class Item : IExtensibleDataObject
{
[DataMember]
public string Name { get; set; }

public ExtensionDataObject ExtensionData { get; set; }
}

      3、新建ItemV2.cs类,代码如下:

[DataContract(Name = "Item", Namespace = "http://schemas.xinhaijulan.com/demos/IExtensibleDataObjectApp")]
public class ItemV2 : IExtensibleDataObject
{
[DataMember]
public int Id { get; set; }
[DataMember]
public string Name { get; set; }

public ExtensionDataObject ExtensionData { get; set; }
}

      注意:Item.cs与ItemV2.cs都继承且实现了IExtensibleDataObject接口。

      4、新建ItemNo.cs与ItemV2No.cs类,这2个类并没有实现IExtensibleDataObject接口,代码如下:

[DataContract(Name = "Item", Namespace = "http://schemas.xinhaijulan.com/demos/IExtensibleDataObjectApp")]
public class ItemNo
{
[DataMember]
public string Name { get; set; }
}

 

[DataContract(Name = "Item", Namespace = "http://schemas.xinhaijulan.com/demos/IExtensibleDataObjectApp")]
public class ItemV2No
{
[DataMember]
public int Id { get; set; }
[DataMember]
public string Name { get; set; }
}

      5、在Program类中新建方法SerializingItemV2、SerializingItem与DeserializeItemV2方法,这三个方法为对实现了IExtensibleDataObject数据契约类进行序列化与反序列化,代码如下:

代码

static void SerializingItemV2(string path)
{
ItemV2 itemV2
= new ItemV2();
itemV2.Name
= "Name";
itemV2.Id
= 88;

DataContractSerializer ser
=
new DataContractSerializer(typeof(ItemV2));

FileStream fs
= new FileStream(path, FileMode.Create);
ser.WriteObject(fs, itemV2);
fs.Close();

Console.WriteLine(
"Serializing ItemV2" + Environment.NewLine + "Id:{0}" + Environment.NewLine + "Name:{1}", itemV2.Id, itemV2.Name);
}

static void SerializingItem(string path)
{
DataContractSerializer ser
=
new DataContractSerializer(typeof(Item));

FileStream fs
= new FileStream(path, FileMode.Open);
XmlDictionaryReader reader
=
XmlDictionaryReader.CreateTextReader(fs,
new XmlDictionaryReaderQuotas());

Item item
= ser.ReadObject(reader, false) as Item;
fs.Close();
Console.WriteLine(
"Deserialize to Item" + Environment.NewLine + "Old Name:{0}", item.Name);

item.Name
= "NewName";
fs
= new FileStream(path, FileMode.Create);
ser.WriteObject(fs, item);
fs.Close();
Console.WriteLine(
"Serializing Item" + Environment.NewLine + "New Name:{0}", item.Name);
}

static void DeserializeItemV2(string path)
{
FileStream fs
= new FileStream(path, FileMode.Open);
DataContractSerializer ser
= new DataContractSerializer(typeof(ItemV2));

ItemV2 itemV2
= ser.ReadObject(fs) as ItemV2;
fs.Close();
Console.WriteLine(
"Deserialize to ItemV2" + Environment.NewLine + "Id:{0}" + Environment.NewLine + "Name:{1}", itemV2.Id, itemV2.Name);
}

      6、在Program类中新建方法SerializingItemV2No、SerializingItemNo与DeserializeItemV2No方法,这三个方法为对没有实现了IExtensibleDataObject数据契约类进行序列化与反序列化,代码如下:

代码

static void SerializingItemV2No(string path)
{
ItemV2No itemV2
= new ItemV2No();
itemV2.Name
= "Name";
itemV2.Id
= 88;

DataContractSerializer ser
=
new DataContractSerializer(typeof(ItemV2No));

FileStream fs
= new FileStream(path, FileMode.Create);
ser.WriteObject(fs, itemV2);
fs.Close();

Console.WriteLine(
"Serializing ItemV2" + Environment.NewLine + "Id:{0}" + Environment.NewLine + "Name:{1}", itemV2.Id, itemV2.Name);
}

static void SerializingItemNo(string path)
{
DataContractSerializer ser
=
new DataContractSerializer(typeof(ItemNo));

FileStream fs
= new FileStream(path, FileMode.Open);
XmlDictionaryReader reader
=
XmlDictionaryReader.CreateTextReader(fs,
new XmlDictionaryReaderQuotas());

ItemNo item
= ser.ReadObject(reader, false) as ItemNo;
fs.Close();
Console.WriteLine(
"Deserialize to Item" + Environment.NewLine + "Old Name:{0}", item.Name);

item.Name
= "NewName";
fs
= new FileStream(path, FileMode.Create);
ser.WriteObject(fs, item);
fs.Close();
Console.WriteLine(
"Serializing Item" + Environment.NewLine + "New Name:{0}", item.Name);
}

static void DeserializeItemV2No(string path)
{
FileStream fs
= new FileStream(path, FileMode.Open);
DataContractSerializer ser
= new DataContractSerializer(typeof(ItemV2No));

ItemV2No itemV2
= (ItemV2No)ser.ReadObject(fs);
fs.Close();
Console.WriteLine(
"Deserialize to ItemV2" + Environment.NewLine + "Id:{0}" + Environment.NewLine + "Name:{1}", itemV2.Id, itemV2.Name);
}

      7、在Main方法中添加代码,如下:

代码
static void Main(string[] args)
{
try
{
Console.WriteLine(
"----------Use IExtensibleDataObject Begin----------");
Console.WriteLine();

SerializingItemV2(
"v2.xml");
Console.WriteLine();

SerializingItem(
"v2.xml");
Console.WriteLine();

DeserializeItemV2(
"v2.xml");
Console.WriteLine(
"Id value saved.");
Console.WriteLine();

Console.WriteLine(
"----------Use IExtensibleDataObject End----------" + Environment.NewLine);


Console.WriteLine(
"----------UnUse IExtensibleDataObject Begin----------");
Console.WriteLine();

SerializingItemV2No(
"v2No.xml");
Console.WriteLine();

SerializingItemNo(
"v2No.xml");
Console.WriteLine();

DeserializeItemV2No(
"v2No.xml");
Console.WriteLine(
"Id value lose.");
Console.WriteLine();

Console.WriteLine(
"----------UnUse IExtensibleDataObject Begin----------");
}
catch (SerializationException ex)
{
Console.WriteLine(
"{0}: {1}", ex.Message, ex.StackTrace);
}

Console.ReadLine();
}

 

      8、运行此项目,可以看到如下输出:

----------Use IExtensibleDataObject Begin----------

Serializing ItemV2
Id:
88
Name:Name

Deserialize to Item
Old Name:Name
Serializing Item
New Name:NewName

Deserialize to ItemV2
Id:
88
Name:NewName
Id value saved.

----------Use IExtensibleDataObject End----------

----------UnUse IExtensibleDataObject Begin----------

Serializing ItemV2
Id:
88
Name:Name

Deserialize to Item
Old Name:Name
Serializing Item
New Name:NewName

Deserialize to ItemV2
Id:
0
Name:NewName
Id value lose.

----------UnUse IExtensibleDataObject Begin----------

 

      从以上输出我们可以看到,在使用了IExtensibleDataObject的序列化与反序列化过程中,数据并没有丢失,而在没有使用了IExtensibleDataObject的序列化与反序列化的过程中,数据有所丢失。

 

      虽然IExtensibleDataObject给WCF的版本更新带来一定的兼容性,但也带来一定的风险与资源浪费,然而我们可以通过配置或代码方式关闭此特性。

      配置方式:

<serviceBehaviors>
<behavior name="serviceBehavior">
<dataContractSerializer ignoreExtensionDataObject="true"/>
</behavior>
</serviceBehaviors>

      代码方式:

[ServiceBehavior(IgnoreExtensionDataObject=true)]
public class ExplicitService : IExplicitService
{
}

      至此,WCF契约版本管理—IExtensibleDataObject介绍完毕。

      点击下载DEMO

作者:心海巨澜
出处:http:
//xinhaijulan.cnblogs.com
版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
posted on 2010-10-13 22:07  心海巨澜  阅读(3170)  评论(8编辑  收藏  举报