WCF 契约版本管理—IExtensibl…

      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的版本更新带来一定的兼容性,但也带来一定的风险与资源浪费,然而我们可以通过配置或代码方式关闭此特性。

      配置方式:

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

      代码方式:

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

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

 

 

本文转自:http://www.cnblogs.com/xinhaijulan/archive/2010/10/13/1850598.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值