对象序列化之 替换(Surrogate)
有可能存在一种情况,实体类型无法进行序列化或需要在序列化的方式上进行更改,如 第三方组件供应商提供的类型或者没有源代码的组件。 对于这种情况,WCF提供IDataContractSurrogate 接口 来实现一个替身类解决此类问题。
解决问题的步骤:
1. 定义数据契约来表示序列化的类型;
2. 定义实现序列化替身的操作类,实现IDataContractSurrogate接口,并至少实现其三个方法: GetDataContractType、GetDeserializedObject、GetObjectToSerialize ,其中GetDataContractType方法会向DataContractSerializer 返回需要序列化的类型,而GetObjectToSerialize和GetDeserializedObject会实际执行序列化和反序列化。
以下代码:
假设 Employee 无法实现序列化,以EmployeeSurrogated 作为其替身类,以EmpoyyeeSurrogate实现操作,代码如下:
EmployeeSurrogated 定义:
[DataContract]
internal class EmployeeSurrogated
{
public EmployeeSurrogated(int employeeID, string firstName, string lastName)
{
this.employeeID = employeeID;
this.firstName = firstName;
this.lastName = lastName;
}
[DataMember]
private int employeeID;
[DataMember]
private string firstName;
[DataMember]
private string lastName;
public int EmployeeID
{
get { return this.employeeID; }
}
public string FirstName
{
get { return this.firstName; }
}
public string LastName
{
get { return this.lastName; }
}
}
EmployeeSurrogate 操作类:
public class EmployeeSurrogate : IDataContractSurrogate
{
public object GetCustomDataToExport(Type clrType, Type dataContractType)
{
return null;
}
public object GetCustomDataToExport(System.Reflection.MemberInfo memberInfo, Type dataContractType)
{
return null;
}
/// <summary>
/// 向DataContractSerializer 返回需要序列化的类型
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
public Type GetDataContractType(Type type)
{
if (typeof(Employee).IsAssignableFrom(type))
{
return typeof(EmployeeSurrogated);
}
return type;
}
/// <summary>
/// 执行反序列化后应返回的实际类型
/// </summary>
/// <param name="obj"></param>
/// <param name="targetType"></param>
/// <returns></returns>
public object GetDeserializedObject(object obj, Type targetType)
{
if (obj is EmployeeSurrogated)
{
EmployeeSurrogated oldEmployee = obj as EmployeeSurrogated;
Employee newEmployee = new Employee()
{
EmployeeID = oldEmployee.EmployeeID,
FirstName = oldEmployee.FirstName,
LastName = oldEmployee.LastName
};
return newEmployee;
}
return obj;
}
public void GetKnownCustomDataTypes(System.Collections.ObjectModel.Collection<Type> customDataTypes)
{
throw new NotImplementedException();
}
/// <summary>
/// 将无法序列化的对象转化会替身类性
/// </summary>
/// <param name="obj"></param>
/// <param name="targetType"></param>
/// <returns></returns>
public object GetObjectToSerialize(object obj, Type targetType)
{
if (obj is Employee)
{
Employee oldEmployee = obj as Employee;
EmployeeSurrogated newEmployee = new EmployeeSurrogated(oldEmployee.EmployeeID, oldEmployee.FirstName, oldEmployee.LastName);
return newEmployee;
}
return obj;
}
public Type GetReferencedTypeOnImport(string typeName, string typeNamespace, object customData)
{
if (typeNamespace.Equals(@"http://schemas.datacontract.org/2004/07/EmplyeeSurrogated"))
{
if (typeName.Equals("EmployeeSurrogated"))
{
return typeof(Employee);
}
}
return null;
}
public CodeTypeDeclaration ProcessImportedType(CodeTypeDeclaration typeDeclaration, CodeCompileUnit compileUnit)
{
return typeDeclaration;
}
}
序列化方式:
序列化器: 注意 DataContractSerializer 的实例化调用的构造方法,此关键操作导致可以实现替代的序列化;
public static string TryToSerialize(object obj)
{
DataContractSerializer serializer = new DataContractSerializer(obj.GetType());
using (StringWriter strWriter = new StringWriter())
{
using (XmlWriter xWriter = XmlWriter.Create(strWriter))
{
try
{
serializer.WriteObject(xWriter, obj);
xWriter.Flush();
return strWriter.ToString();
}
catch (Exception ex)
{
Console.WriteLine("Can not serialize without a surrogate : {0}", ex);
}
}
}
return string.Empty;
}
public static string SerializeUsingSurrogate(object obj, IDataContractSurrogate surrogateObj)
{
DataContractSerializer serializer = new DataContractSerializer(obj.GetType(), null, int.MaxValue, false, false, surrogateObj);
return SerializeUsingSurrogate(serializer, obj);
}
public static string SerializeUsingSurrogate(DataContractSerializer serializer, object obj)
{
using (StringWriter strWriter = new StringWriter())
{
using (XmlWriter xWriter = XmlWriter.Create(strWriter))
{
serializer.WriteObject(xWriter, obj);
xWriter.Flush();
return strWriter.ToString();
}
}
}
public static object DeserializeUsingSurrogate(Type sourceType, IDataContractSurrogate surrogateObj, string objXml)
{
DataContractSerializer serializer = new DataContractSerializer(sourceType, null, int.MaxValue, false, false, surrogateObj);
return DeserializeUsingSurrogate(serializer, objXml);
}
public static object DeserializeUsingSurrogate(DataContractSerializer serializer, string objXml)
{
using (StringReader strReader = new StringReader(objXml))
{
using (XmlReader xReader = XmlReader.Create(strReader))
{
return serializer.ReadObject(xReader);
}
}
}
最后执行:
static void SerializeSurrogate()
{
Employee e = new Employee()
{
EmployeeID = 1,
FirstName = "jerry",
LastName = "shi"
};
Console.WriteLine("{0},{1},{2}", e.EmployeeID, e.FirstName, e.LastName);
SerializeHelper.TryToSerialize(e);
string objXml = SerializeHelper.SerializeUsingSurrogate(e, new EmployeeSurrogate());
Console.WriteLine(objXml);
Employee newobj = (Employee)SerializeHelper.DeserializeUsingSurrogate(e.GetType(), new EmployeeSurrogate(), objXml);
Console.WriteLine("{0},{1},{2}", newobj.EmployeeID, newobj.FirstName, newobj.LastName);
Console.WriteLine("Press <Enter> to continute...");
Console.ReadLine();
}
结果说明:


浙公网安备 33010602011771号