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类,代码如下:
public class Item : IExtensibleDataObject
{
[DataMember]
public string Name { get ; set ; }
public ExtensionDataObject ExtensionData { get ; set ; }
}
3、新建ItemV2.cs类,代码如下:
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接口,代码如下:
public class ItemNo
{
[DataMember]
public string Name { get ; set ; }
}
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方法中添加代码,如下:
{
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、运行此项目,可以看到如下输出:
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的版本更新带来一定的兼容性,但也带来一定的风险与资源浪费,然而我们可以通过配置或代码方式关闭此特性。
配置方式:
< behavior name = " serviceBehavior " >
< dataContractSerializer ignoreExtensionDataObject = " true " />
</ behavior >
</ serviceBehaviors >
代码方式:
public class ExplicitService : IExplicitService
{
}
至此,WCF契约版本管理—IExtensibleDataObject介绍完毕。
出处:http: //xinhaijulan.cnblogs.com
版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。