• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
皇图霸业谈笑间
更高、更快、更强
博客园    首页    新随笔    联系   管理    订阅  订阅
关于Protobuf类型继承问题

参考文献:

 

http://code.google.com/p/protobuf-net/

http://stackoverflow.com/questions/3100207/why-i-have-to-use-protoinclude

 

using System;
using System.IO;
using System.Text.RegularExpressions;
using ProtoBuf;
using ProtoBuf.Meta;

namespace TestConsole
{
    public class ProtobufTest : ITest
    {
        private static TimeSpan ts = TimeSpan.FromSeconds(1);
        /// <summary>
        
/// 临时测试使用
        
/// </summary>
        public void Run()
        {
            {
                Console.WriteLine("v1的序列化和反序列化测试");
                Person p = new Student() { Sex = true, Name = "张三", School = "福州3中" };
                var arr1 = ProtobufSerialize(p);
                var s1 = ProtobufDeserialize<Student>(arr1);
                Console.WriteLine(s1.Sex + ";" + s1.Name + ";" + s1.School);
                var s2 = ProtobufDeserialize<Person>(arr1);
                Console.WriteLine(s2.Sex + ";" + s2.Name);
            }
            Console.WriteLine();

            {
                Console.WriteLine("v2的序列化和反序列化测试");
                Animal bird = new Bird() { Sex = true, Name = "海鸥", CanFly = true };
                var arr2 = ProtobufSerialize(bird);
                var b1 = ProtobufDeserialize<Bird>(arr2);
                Console.WriteLine(b1.Sex + ";" + b1.Name + ";" + b1.CanFly);
                var b2 = ProtobufDeserialize<Animal>(arr2);
                Console.WriteLine(b2.Sex + ";" + b2.Name);
            }
        }

        #region 序列化和反序列化的方法
        /// <summary>
        
/// 使用protobuf把对象序列化为Byte数组
        
/// </summary>
        
/// <typeparam name="T">需要反序列化的对象类型,必须声明[ProtoContract]特征,且相应属性必须声明[ProtoMember(序号)]特征</typeparam>
        
/// <param name="obj"></param>
        
/// <returns></returns>
        public static Byte[] ProtobufSerialize<T>(T obj)
        {
            using (var memory = new MemoryStream())
            {
                Serializer.Serialize(memory, obj);
                return memory.ToArray();
            }
        }

        /// <summary>
        
/// 使用protobuf反序列化二进制数组为对象
        
/// </summary>
        
/// <typeparam name="T">需要反序列化的对象类型,必须声明[ProtoContract]特征,且相应属性必须声明[ProtoMember(序号)]特征</typeparam>
        
/// <param name="data"></param>
        public static T ProtobufDeserialize<T>(Byte[] data) where T : class
        {
            using (var memory = new MemoryStream(data))
            {
                return Serializer.Deserialize<T>(memory);
            }
        }
        #endregion
    }

    #region v1里的使用属性的方法,每个class都必须加上ProtoContract属性,且ProtoInclude加上子类的定义,每个属性都要加上ProtoMember
    [ProtoContract]
    [ProtoInclude(3, typeof(Student))]
    public class Person
    {
        [ProtoMember(1)]
        public bool Sex { get; set; }

        [ProtoMember(2)]
        public string Name { get; set; }
    }

    [ProtoContract]
    public class Student : Person
    {
        [ProtoMember(11)]
        public string School { get; set; }
    }
    #endregion


    #region v2里的使用RuntimeTypeModel,可以在运行时动态定义,关键就是在序列化必须保证会运行到Include的代码,比如下面的Bird的静态构造函数
    public class Animal
    {
        public bool Sex { get; set; }
        public string Name { get; set; }
    }

    public class Bird : Animal
    {
        static Bird()
        {
            RuntimeTypeModel a = RuntimeTypeModel.Default;
            a[typeof(Animal)].Add(1, "Sex").Add(2, "Name").AddSubType(3, typeof(Bird));// 这一句也可以写在Animal的static定义里
            a[typeof(Bird)].Add(1, "CanFly");
        }
        public bool CanFly { get; set; }
    }
    #endregion

}
posted on 2012-11-06 15:56  布颜书  阅读(24066)  评论(1)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3