最近一直在做windows phone 7手机上面的应用程序,学到了一些除了微软这套东西以外的知识,除了Funambol这个库以外(等到完全研究懂了再写笔记),还有protobuf-net这个对数据进行序列化的工具。
其实protobuf-net只是protobuf在.net平台上的应用,而protobuf是google提供的供数据序列化的工具,在网上搜索能找到一大堆相关资料,估计这个工具对数据的处理速度和节省空间的能力都很强,所以很多人才用这个工具。在http://code.google.com/p/protobuf/ 上面有详细的说明,加上我对JAVA不感兴趣,在此就不做什么介绍了。
至于protobuf-net,则是由一个人进行开发的,这个程序员在自己的博客上贴出了很多资料,告诉人们怎么使用,地址在这里:http://marcgravell.blogspot.com/search/label/protobuf-net (需翻墙)http://code.google.com/p/protobuf-net/(这里是代码维护地址)
下面来说说如何使用
下载压缩包,解压后会发现有很多平台,至于我就需要选择windows phone平台,里面有三个文件
先把protobuf-net.dll 添加到工程引用
编写自定义的protobuf类,在我的程序中类(ProtoBuf.cs)如下:
using ProtoBuf;
using System.Collections.Generic;
namespace SyncControls
{
[ProtoContract]
public class PBCalendarItem
{
// required int64 pid = 1;
[ProtoMember(1,IsRequired=true)]
public long pid { get; set; }
// required string title = 2;
[ProtoMember(2, IsRequired = true)]
public string title { get; set; }
// required int64 created = 3;
[ProtoMember(3, IsRequired = true)]
public long created { get; set; }
// required int64 modified = 4;
[ProtoMember(4, IsRequired = true)]
public long modified { get; set; }
// optional int64 owner_id = 5;
[ProtoMember(5, IsRequired = false)]
public long owner_id { get; set; }
// optional string location = 6;
[ProtoMember(6, IsRequired = false)]
public string location { get; set; }
// optional string description = 7;
[ProtoMember(7, IsRequired = false)]
public string description { get; set; }
// optional string timezone = 8;
[ProtoMember(8, IsRequired = false)]
public string timezone { get; set; }
// optional int32 is_primary = 9;
[ProtoMember(9, IsRequired = false)]
public int is_primary { get; set; }
// optional int32 is_public = 10;
[ProtoMember(10, IsRequired = false)]
public int is_public { get; set; }
// optional int32 pub_status_only = 11;
[ProtoMember(11, IsRequired = false)]
public int pub_status_only { get; set; }
// optional int32 searchable = 12;
[ProtoMember(12, IsRequired = false)]
public int searchable { get; set; }
// optional string data_domain = 13;
[ProtoMember(13, IsRequired = false)]
public string data_domain { get; set; }
// optional int32 calendar_type = 14;
[ProtoMember(14, IsRequired = false)]
public int calendar_type { get; set; }
// optional string sync_state = 15;
[ProtoMember(15, IsRequired = false)]
public string sync_state { get; set; }
// optional int32 access_type = 16;
[ProtoMember(16, IsRequired = false)]
public int access_type { get; set; }
// optional string uuid = 17;
[ProtoMember(17, IsRequired = false)]
public string uuid { get; set; }
// optional string color = 18;
[ProtoMember(18, IsRequired = false)]
public string color { get; set; }
}
[ProtoContract]
public class PBScheduleItem
{
// required int64 pid = 1;
[ProtoMember(1, IsRequired = true)]
public long pid { get; set; }
// required int64 calendar_id = 2;
[ProtoMember(2, IsRequired = true)]
public long calendar_id { get; set; }
// required int64 created = 3;
[ProtoMember(3, IsRequired = true)]
public long created { get; set; }
// required int64 modified = 4;
[ProtoMember(4, IsRequired = true)]
public long modified { get; set; }
// required string calendar_type = 5;
[ProtoMember(5, IsRequired = true)]
public string calendar_type { get; set; }
// optional string sync_state = 6;
[ProtoMember(6, IsRequired = false)]
public string sync_state { get; set; }
// optional int64 owner_id = 7;
[ProtoMember(7, IsRequired = false)]
public long owner_id { get; set; }
// optional int64 start_time = 8;
[ProtoMember(8, IsRequired = false)]
public long start_time { get; set; }
// optional int32 duration = 9;
[ProtoMember(9, IsRequired = false)]
public int duration { get; set; }
// optional int32 allday_event = 10;
[ProtoMember(10, IsRequired = false)]
public int allday_event { get; set; }
// optional int32 access_type = 11;
[ProtoMember(11, IsRequired = false)]
public int access_type { get; set; }
// optional int32 status_busy = 12;
[ProtoMember(12, IsRequired = false)]
public int status_busy { get; set; }
// optional string title = 13;
[ProtoMember(13, IsRequired = false)]
public string title { get; set; }
// optional string location = 14;
[ProtoMember(14, IsRequired = false)]
public string location { get; set; }
// optional string description = 15;
[ProtoMember(15, IsRequired = false)]
public string description { get; set; }
// optional string url = 16;
[ProtoMember(16, IsRequired = false)]
public string url { get; set; }
// optional int32 check_completed = 17;
[ProtoMember(17, IsRequired = false)]
public int check_completed { get; set; }
// optional int32 repeat_type = 18;
[ProtoMember(18, IsRequired = false)]
public int repeat_type { get; set; }
// optional int32 repeat_finished = 19;
[ProtoMember(19, IsRequired = false)]
public int repeat_finished { get; set; }
// optional int64 repeat_stop_time = 20;
[ProtoMember(20, IsRequired = false)]
public long repeat_stop_time { get; set; }
// optional int32 repeat_count = 21;
[ProtoMember(21, IsRequired = false)]
public int repeat_count { get; set; }
// optional int32 repeat_frequency = 22;
[ProtoMember(22, IsRequired = false)]
public int repeat_frequency { get; set; }
// optional string repeat_month = 23;
[ProtoMember(23, IsRequired = false)]
public string repeat_month { get; set; }
// optional string repeat_monthday = 24;
[ProtoMember(24, IsRequired = false)]
public string repeat_monthday { get; set; }
// optional string repeat_day = 25;
[ProtoMember(25, IsRequired = false)]
public string repeat_day { get; set; }
// optional string repeat_weekno = 26;
[ProtoMember(26, IsRequired = false)]
public string repeat_weekno { get; set; }
// optional string repeat_yearday = 27;
[ProtoMember(27, IsRequired = false)]
public string repeat_yearday { get; set; }
// optional string timezone = 28;
[ProtoMember(28, IsRequired = false)]
public string timezone { get; set; }
// optional string uuid = 29;
[ProtoMember(29, IsRequired = false)]
public string uuid { get; set; }
// optional string calendar_uuid = 30;
[ProtoMember(30, IsRequired = false)]
public string calendar_uuid { get; set; }
[ProtoMember(31, IsRequired = false)]
public List<PBScheduleExceptionItem> scheduleExceptions { get; private set; }
[ProtoMember(32, IsRequired = false)]
public List<PBScheduleAlarmItem> scheduleAlarms { get; private set; }
[ProtoMember(33, IsRequired = false)]
public List<PBScheduleUserItem> scheduleUsers { get; private set; }
[ProtoMember(34, IsRequired = false)]
public List<PBScheduleShareItem> scheduleShares { get; private set; }
public PBScheduleItem()
{
scheduleExceptions = new List<PBScheduleExceptionItem>();
scheduleAlarms = new List<PBScheduleAlarmItem>();
scheduleShares = new List<PBScheduleShareItem>();
scheduleUsers = new List<PBScheduleUserItem>();
}
}
[ProtoContract]
public class PBScheduleExceptionItem
{
// required int64 pid = 1;
[ProtoMember(1, IsRequired = true)]
public long pid { get; set; }
// required int32 schedule_id = 2;
[ProtoMember(2, IsRequired = true)]
public int schedule_id { get; set; }
// required string excep_date = 3;
[ProtoMember(3, IsRequired = true)]
public string excep_date { get; set; }
// optional string sync_state = 4;
[ProtoMember(4, IsRequired = false)]
public string sync_state { get; set; }
}
[ProtoContract]
public class PBScheduleAlarmItem
{
// required int64 pid = 1;
[ProtoMember(1, IsRequired = true)]
public long pid { get; set; }
// optional int64 created = 2;
[ProtoMember(2, IsRequired = false)]
public long created { get; set; }
// optional int64 modified = 3;
[ProtoMember(3, IsRequired = false)]
public long modified { get; set; }
// required int64 schedule_id = 4;
[ProtoMember(4, IsRequired = true)]
public long schedule_id { get; set; }
// required int64 user_id = 5;
[ProtoMember(5, IsRequired = true)]
public long user_id { get; set; }
// required int64 alarm_id = 6;
[ProtoMember(6, IsRequired = true)]
public long alarm_id { get; set; }
// required int32 before_minutes = 7;
[ProtoMember(7, IsRequired = true)]
public int before_minutes { get; set; }
// optional int64 next_alarm = 8;
[ProtoMember(8, IsRequired = false)]
public long next_alarm { get; set; }
// optional string sync_state = 9;
[ProtoMember(9, IsRequired = false)]
public string sync_state { get; set; }
}
[ProtoContract]
public class PBScheduleUserItem
{
// required int64 pid = 1;
[ProtoMember(1, IsRequired = true)]
public long pid { get; set; }
// required int64 schedule_id = 2;
[ProtoMember(2, IsRequired = true)]
public long schedule_id { get; set; }
// required int64 user_id = 3;
[ProtoMember(3, IsRequired = true)]
public long user_id { get; set; }
// required int32 is_owner = 4;
[ProtoMember(4, IsRequired = true)]
public int is_owner { get; set; }
// required int32 participant_status = 5;
[ProtoMember(5, IsRequired = true)]
public int participant_status { get; set; }
// optional int32 allow_edit = 6;
[ProtoMember(6, IsRequired = false)]
public int allow_edit { get; set; }
// optional int32 allow_invite_others = 7;
[ProtoMember(7, IsRequired = false)]
public int allow_invite_others { get; set; }
// optional int32 allow_view_participants = 8;
[ProtoMember(8, IsRequired = false)]
public int allow_view_participants { get; set; }
// optional string participant_comment = 9;
[ProtoMember(9, IsRequired = false)]
public string participant_comment { get; set; }
// optional string sync_state = 10;
[ProtoMember(10, IsRequired = false)]
public string sync_state { get; set; }
}
[ProtoContract]
public class PBScheduleShareItem
{
// required int64 pid = 1;
[ProtoMember(1, IsRequired = true)]
public long pid { get; set; }
// optional int64 created = 2;
[ProtoMember(2, IsRequired = false)]
public long created { get; set; }
// optional int64 modified = 3;
[ProtoMember(3, IsRequired = false)]
public long modified { get; set; }
// optional string sync_state = 4;
[ProtoMember(4, IsRequired = false)]
public string sync_state { get; set; }
// required int64 schedule_id = 5;
[ProtoMember(5, IsRequired = true)]
public long schedule_id { get; set; }
// required int64 contact_id = 6;
[ProtoMember(6, IsRequired = true)]
public long contact_id { get; set; }
// optional string fullname = 7;
[ProtoMember(7, IsRequired = false)]
public string fullname { get; set; }
// optional string mobile = 8;
[ProtoMember(8, IsRequired = false)]
public string mobile { get; set; }
// optional string send_state = 9;
[ProtoMember(9, IsRequired = false)]
public string send_state { get; set; }
}
[ProtoContract]
public class PBNoteItem
{
// required int64 pid = 1;
[ProtoMember(1, IsRequired = true)]
public long pid { get; set; }
// required int64 created = 2;
[ProtoMember(2, IsRequired = true)]
public long created { get; set; }
// required int64 modified = 3;
[ProtoMember(3, IsRequired = true)]
public long modified { get; set; }
// optional string sync_state = 4;
[ProtoMember(4, IsRequired = false)]
public string sync_state { get; set; }
// optional string title = 5;
[ProtoMember(5, IsRequired = false)]
public string title { get; set; }
// optional int64 owner_id = 6;
[ProtoMember(6, IsRequired = false)]
public long owner_id { get; set; }
// optional int32 state = 7;
[ProtoMember(7, IsRequired = false)]
public int state { get; set; }
// optional int32 priority = 8;
[ProtoMember(8, IsRequired = false)]
public int priority { get; set; }
// optional int64 finish_time = 9;
[ProtoMember(9, IsRequired = false)]
public long finish_time { get; set; }
// optional int64 deadline = 10;
[ProtoMember(10, IsRequired = false)]
public long deadline { get; set; }
// optional string tags = 11;
[ProtoMember(11, IsRequired = false)]
public string tags { get; set; }
// optional int32 seq = 12;
[ProtoMember(12, IsRequired = false)]
public int seq { get; set; }
// optional string uuid = 13;
[ProtoMember(13, IsRequired = false)]
public string uuid { get; set; }
}
}
再编写转换类,这里是PBConverter.cs
using DataBase;
using System;
using DataManager;
using Utilities;
namespace SyncControls
{
public static class DataBaseExMethods
{
#region Calendar
public static PBCalendarItem ToProtoBuf(this CalendarItem t)
{
PBCalendarItem item = new PBCalendarItem();
item.pid = t.Id;
item.title = t.Title;
item.created = t.Created;
item.modified = t.Modified;
item.owner_id = t.OwnerId;
item.location = t.Location;
item.description = t.Description;
item.timezone = t.TimeZone;
item.is_primary = t.IsPrimary ? 1 : 0;
item.is_public = t.IsPublic ? 1 : 0;
item.pub_status_only = t.PubStatusOnly ? 1 : 0;
item.searchable = t.Searchable ? 1 : 0;
item.data_domain = t.DataDomain;
item.calendar_type = t.CalendarType;
item.access_type = t.AccessType;
item.sync_state = t.SyncState;
item.uuid = t.UUID;
item.color = t.Color;
return item;
}
public static void FromProtoBuf(this CalendarItem t, PBCalendarItem item)
{
t.Id = item.pid;
t.Title = item.title;
t.Created = item.created;
t.Modified = item.modified;
t.OwnerId = item.owner_id;
t.Location = item.location;
t.Description = item.description;
t.TimeZone = item.timezone;
t.IsPrimary = item.is_primary == 1;
t.IsPublic = item.is_public == 1;
t.PubStatusOnly = item.pub_status_only == 1;
t.Searchable = item.searchable == 1;
t.DataDomain = item.data_domain;
t.CalendarType = item.calendar_type;
t.AccessType = item.access_type;
t.SyncState = item.sync_state;
t.UUID = item.uuid;
t.Color = item.color;
}
#endregion
#region Note
public static PBNoteItem ToProtoBuf(this NoteItem t)
{
PBNoteItem item = new PBNoteItem();
item.pid = t.Id;
item.title = t.Title;
item.created = t.Created;
item.modified = t.Modified;
item.sync_state = t.SyncState;
item.title = t.Title;
item.owner_id = t.OwnerId;
item.state = t.State;
item.priority = t.Priority;
item.finish_time = t.FinishTime;
item.deadline = t.Deadline;
item.tags = t.Tags;
item.seq = t.Seq;
item.uuid = t.UUID;
return item;
}
public static void FromProtoBuf(this NoteItem t, PBNoteItem item)
{
t.Id = item.pid;
t.Title = item.title;
t.Created = item.created;
t.Modified = item.modified;
t.SyncState = item.sync_state;
t.Title = item.title;
t.OwnerId = item.owner_id;
t.State = item.state;
t.Priority = item.priority;
t.FinishTime = item.finish_time;
t.Deadline = item.deadline;
t.Tags = item.tags;
t.Seq = item.seq;
t.UUID = item.uuid;
}
#endregion
#region Schedule
public static PBScheduleItem ToProtoBuf(this ScheduleItem t)
{
PBScheduleItem item = new PBScheduleItem();
item.pid = t.Id;
item.calendar_id = t.CalendarId;
item.created = t.Created;
item.modified = t.Modified;
item.calendar_type = t.CalendarType;
item.sync_state = t.SyncState;
item.owner_id = t.OwnerId;
item.start_time = UnixTimestampConverter.ConvertLocalToTimestamp(t.StartTime);
item.duration = t.Duration;
item.allday_event = t.AllDayEvent ? 1 : 0;
item.access_type = t.AccessType;
item.status_busy = t.StatusBusy ? 1 : 0;
item.title = t.Title;
item.location = t.Location;
item.description = t.Description;
item.url = t.Url;
item.check_completed = t.Completed ? 1 : 0;
item.repeat_type = t.RepeatType;
item.repeat_finished = t.RepeatFinished ? 1 : 0;
item.repeat_stop_time = t.RepeatStopTime;
item.repeat_count = t.RepeatCount;
item.repeat_frequency = t.RepeatFrequency;
item.repeat_month = t.RepeatMonth;
item.repeat_monthday = t.RepeatMonthDay;
item.repeat_day = t.RepeatDay;
item.repeat_weekno = t.RepeatWeekNumber;
item.repeat_yearday = t.RepeatYearDay;
item.timezone = t.TimeZone;
item.uuid = t.UUID;
item.calendar_uuid = CalendarManager.GetCalendarUUID(t.CalendarId);
if (item.calendar_uuid == "")
{
return null;
}
return item;
}
public static void FromProtoBuf(this ScheduleItem t, PBScheduleItem item)
{
t.Id = item.pid;
t.CalendarId = CalendarManager.GetCalendarID(item.calendar_uuid);
t.Created = item.created;
t.Modified = item.modified;
t.CalendarType = item.calendar_type;
t.SyncState = item.sync_state;
t.OwnerId = item.owner_id;
t.StartTime = UnixTimestampConverter.ConvertLocalFromTimestamp(item.start_time);
t.Duration = item.duration;
t.AllDayEvent = item.allday_event == 1;
t.AccessType = item.access_type;
t.StatusBusy = item.status_busy == 1;
t.Title = item.title;
t.Location = item.location;
t.Description = item.description;
t.Url = item.url;
t.CheckCompleted = item.check_completed == 1;
t.RepeatType = item.repeat_type;
t.RepeatFinished = item.repeat_finished == 1;
t.RepeatStopTime = item.repeat_stop_time;
t.RepeatCount = item.repeat_count;
t.RepeatFrequency = item.repeat_frequency;
t.RepeatMonth = item.repeat_month;
t.RepeatMonthDay = item.repeat_monthday;
t.RepeatDay = item.repeat_day;
t.RepeatWeekNumber = item.repeat_weekno;
t.RepeatYearDay = item.repeat_yearday;
t.TimeZone = item.timezone;
t.UUID = item.uuid;
}
#endregion
#region ScheduleAlarm
public static PBScheduleAlarmItem ToProtoBuf(this ScheduleAlarmItem t)
{
PBScheduleAlarmItem item = new PBScheduleAlarmItem();
item.pid = t.Id;
item.created = t.Created;
item.modified = t.Modified;
item.sync_state = t.SyncState;
item.schedule_id = t.ScheduleId;
item.user_id = t.UserId;
item.alarm_id = t.AlarmId;
item.before_minutes = t.BeforeMinutes;
return item;
}
public static void FromProtoBuf(this ScheduleAlarmItem t,PBScheduleAlarmItem item)
{
t.Id = item.pid;
t.Created = item.created;
t.Modified = item.modified;
t.SyncState = item.sync_state;
t.ScheduleId = item.schedule_id;
t.UserId = item.user_id;
t.AlarmId = (int)item.alarm_id;
t.BeforeMinutes = item.before_minutes;
}
#endregion
#region ScheduleException
public static PBScheduleExceptionItem ToProtoBuf(this ScheduleExceptionItem t)
{
PBScheduleExceptionItem item = new PBScheduleExceptionItem();
item.pid = t.Id;
item.sync_state = t.SyncState;
item.schedule_id = (int)t.ScheduleId;
item.excep_date = Convert.ToString(t.ExceptDate);
return item;
}
public static void FromProtoBuf(this ScheduleExceptionItem t, PBScheduleExceptionItem item)
{
t.Id = item.pid;
t.SyncState = item.sync_state;
t.ScheduleId = item.schedule_id;
t.ExceptDate = Convert.ToInt64(item.excep_date);
}
#endregion
#region ScheduleShare
public static PBScheduleShareItem ToProtoBuf(this ScheduleShareItem t)
{
PBScheduleShareItem item = new PBScheduleShareItem();
item.pid = t.Id;
item.created = t.Created;
item.modified = t.Modified;
item.sync_state = t.SyncState;
item.schedule_id = t.ScheduleId;
item.fullname = t.FullName;
item.mobile = t.Mobile;
item.send_state = t.SendState;
return item;
}
public static void FromProtoBuf(this ScheduleShareItem t, PBScheduleShareItem item)
{
t.Id = item.pid;
t.Created = item.created;
t.Modified = item.modified;
t.SyncState = item.sync_state;
t.ScheduleId = item.schedule_id;
t.FullName = item.fullname;
t.Mobile = item.mobile;
t.SendState = item.send_state;
}
#endregion
#region ScheduleUser
public static PBScheduleUserItem ToProtoBuf(this ScheduleUserItem t)
{
PBScheduleUserItem item = new PBScheduleUserItem();
item.pid = t.Id;
item.schedule_id = t.ScheduleId;
item.user_id = t.UserId;
item.is_owner = t.IsOwner ? 1 : 0;
item.participant_status = t.ParticipantStatus;
item.allow_edit = t.AllowEdit ? 1 : 0;
item.allow_invite_others = t.AllowInviteOthers ? 1 : 0;
item.allow_view_participants = t.AllowViewParticipants ? 1 : 0;
item.participant_comment = t.ParticipantComment;
item.sync_state = t.SyncState;
return item;
}
public static void FromProtoBuf(this ScheduleUserItem t, PBScheduleUserItem item)
{
t.Id = item.pid;
t.ScheduleId = item.schedule_id;
t.UserId = item.user_id;
t.IsOwner = item.is_owner == 1;
t.ParticipantStatus = item.participant_status;
t.AllowEdit = item.allow_edit == 1;
t.AllowInviteOthers = item.allow_invite_others == 1;
t.AllowViewParticipants = item.allow_view_participants == 1;
t.ParticipantComment = item.participant_comment;
t.SyncState = item.sync_state;
}
#endregion
}
}
使用的时候,只需要按照下面方式写即可
protected override SyncItem GetItemContent(SyncItem item)
{
CalendarItem t = CalendarManager.GetCalendarByID(Convert.ToInt64(item.Key));
PBCalendarItem pbItem = t.ToProtoBuf();
return ToSyncItem(pbItem);
}
private SyncItem ToSyncItem(PBCalendarItem pbItem)
{
SyncItem item = new SyncItem(Convert.ToString(pbItem.pid));
string syncState = pbItem.sync_state;
MemoryStream stream = new MemoryStream();
//序列化
Serializer.Serialize<PBCalendarItem>(stream, pbItem);
item.SetContent(stream.GetBuffer());
return item;
}
private PBCalendarItem FromSyncItem(SyncItem item)
{
byte[] b = item.GetContent();
PBCalendarItem pbItem = null;
try
{
MemoryStream stream = new MemoryStream(b);
//反序列化
pbItem = Serializer.Deserialize<PBCalendarItem>(stream);
}
catch { }
return pbItem;
}
这里是把数据写入到一个内存流里面,而不是通常意义上的文件之中,如果是文件可以看这里的例子
http://hi.baidu.com/jack1865/item/09a3f8ef4c8505f2eb34c957
以上只是对这个工具的简单使用说明而已,现在protobuf-net的作者已经开发出了更强的序列号工具,通过他给的precompiler工具加上自己写的特定框架下的试验工程,编译得到适合该特定框架下的序列化工具。
precompile {some path}\PhoneDto.dll –o:PhoneSerializer.dll –t:MySerializer
Then, just use MySerializer
:
var ser = new MySerializer(); ser.Serialize(output, obj);
看来还有很多知识要学习。