惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

C
Check Point Blog
GbyAI
GbyAI
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
U
Unit 42
美团技术团队
NISL@THU
NISL@THU
C
Cisco Blogs
SecWiki News
SecWiki News
N
Netflix TechBlog - Medium
Forbes - Security
Forbes - Security
Cloudbric
Cloudbric
雷峰网
雷峰网
T
Tailwind CSS Blog
博客园 - 司徒正美
The Register - Security
The Register - Security
L
LangChain Blog
S
Security Affairs
Hacker News - Newest:
Hacker News - Newest: "LLM"
B
Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
T
Threat Research - Cisco Blogs
I
InfoQ
S
Schneier on Security
L
Lohrmann on Cybersecurity
量子位
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Martin Fowler
Martin Fowler
Schneier on Security
Schneier on Security
F
Fortinet All Blogs
TaoSecurity Blog
TaoSecurity Blog
K
Kaspersky official blog
Google DeepMind News
Google DeepMind News
Cisco Talos Blog
Cisco Talos Blog
PCI Perspectives
PCI Perspectives
Attack and Defense Labs
Attack and Defense Labs
WordPress大学
WordPress大学
Microsoft Azure Blog
Microsoft Azure Blog
H
Help Net Security
Project Zero
Project Zero
The GitHub Blog
The GitHub Blog
D
Docker
N
News | PayPal Newsroom
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
H
Hacker News: Front Page
云风的 BLOG
云风的 BLOG
Microsoft Security Blog
Microsoft Security Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
博客园 - 聂微东
Webroot Blog
Webroot Blog
MongoDB | Blog
MongoDB | Blog

博客园 - JerryShi

使用流模式传输大型数据 使用 IExtensibleDataObject 进行往返式序列化 使用 NetDataContractSerializer 共享类型 WCF可序列化方式 序列化 VS 编码 自定义 Behavior 操作行为 之 事务 服务行为 之 元数据 服务行为 之 并发与实例化 基本的WCF编程(实例) WCF Behaviors(行为) WCF 体系结构 WCF服务 使用netTcpBinding 无法打开默认数据库 SharePoint 创建SSP时出现找不到 Windows NT 用户或组 的异常 SQL Server 2008 Mirror 泛型(一) 自定义属性Attribute(三) 自定义属性Attribute(二)
对象序列化之 替换(Surrogate)
JerryShi · 2011-11-19 · via 博客园 - JerryShi

有可能存在一种情况,实体类型无法进行序列化或需要在序列化的方式上进行更改,如 第三方组件供应商提供的类型或者没有源代码的组件。 对于这种情况,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();
        }

结果说明:

序列化替代结果