經常使用的工具包,如Newtonsoft.Json, 它是基於json格式的序列化和反序列化的組件html
json.net 有如下優勢:json
侵入性:能夠不添加attribute,就能進行序列化操做設計模式
靈活性:能夠靈活性配置,好比容許被序列化的成員自定義名字,屏蔽的非序列化屬性成員工具
可讀性: 數據格式比較簡單, 易於讀寫性能
依賴性:能夠序列化成JObject,無需依賴對象進行序列化和泛型化。單元測試
它是基於二進制格式的序列化和反序列化的組件測試
protobuf 有如下優勢:大數據
性能高 : 序列化後體積相比Json和XML很小,適合RPC二進制傳輸
跨語言:支持跨平臺多語言
兼容性:消息格式升級和兼容性還不錯
速度快 :序列化反序列化速度很快,快於Json的處理速度ui
它是基於二進制格式的序列化和反序列化的組件this
messagepack有如下優勢:
性能高:序列化後體積相比Json和XML很小,適合RPC二進制傳輸
跨語言:支持跨平臺多語言
兼容性:消息格式升級和兼容性還不錯
速度快 :序列化反序列化速度很快,快於Json的處理速度
messagepack無論是小數據量仍是大數據量都保持比較穩定的性能,本文中使用messagepack序列化方式。
以下是文件結構:
1.工廠
/// <summary> /// 一個抽象的傳輸消息編解碼器工廠。 /// </summary> public interface ITransportMessageCodecFactory { /// <summary> /// 獲取編碼器。 /// </summary> /// <returns>編碼器實例。</returns> ITransportMessageEncoder GetEncoder(); /// <summary> /// 獲取解碼器。 /// </summary> /// <returns>解碼器實例。</returns> ITransportMessageDecoder GetDecoder(); }
2.編碼器
/// <summary> /// 編碼器 /// </summary> public interface ITransportMessageEncoder { byte[] Encode(TransportMessage message); }
3.解碼器
/// <summary> /// 解碼器 /// </summary> public interface ITransportMessageDecoder { TransportMessage Decode(byte[] data); }
1.工廠
public sealed class MessagePackTransportMessageCodecFactory : ITransportMessageCodecFactory { #region Field private readonly ITransportMessageEncoder _transportMessageEncoder = new MessagePackTransportMessageEncoder(); private readonly ITransportMessageDecoder _transportMessageDecoder = new MessagePackTransportMessageDecoder(); #endregion Field #region Implementation of ITransportMessageCodecFactory /// <inheritdoc /> /// <summary> /// 獲取編碼器 /// </summary> /// <returns></returns> public ITransportMessageEncoder GetEncoder() { return _transportMessageEncoder; } /// <inheritdoc /> /// <summary> /// 獲取解碼器 /// </summary> /// <returns></returns> public ITransportMessageDecoder GetDecoder() { return _transportMessageDecoder; } #endregion Implementation of ITransportMessageCodecFactory }
2.編碼器
public sealed class MessagePackTransportMessageEncoder : ITransportMessageEncoder { #region Implementation of ITransportMessageEncoder public byte[] Encode(TransportMessage transportMessage) { MessagePackTransportMessage messagePackTransportMessage = new MessagePackTransportMessage(transportMessage); return MessagePackSerializer.Serialize(messagePackTransportMessage); } #endregion Implementation of ITransportMessageEncoder }
3.解碼器
public sealed class MessagePackTransportMessageDecoder : ITransportMessageDecoder { #region Implementation of ITransportMessageDecoder public TransportMessage Decode(byte[] data) { MessagePackTransportMessage messagePackTransportMessage = MessagePackSerializer.Deserialize<MessagePackTransportMessage>(data); return messagePackTransportMessage.GetTransportMessage(); } #endregion Implementation of ITransportMessageDecoder }
高層的消息模型:
public class TransportMessage { /// <summary> /// 消息Id。 /// </summary> public string Id { get; set; } /// <summary> /// 消息內容。 /// </summary> public object Content { get; set; } /// <summary> /// 內容類型。 /// </summary> public string ContentType { get; set; } }
因爲MessagePack序列化方式具備侵入性,須要添加 MessagePackObjectAttribute 和 KeyAttribute 特性,所以須要對 TransportMessage 作裝飾:
using MessagePack; [MessagePackObject] public class MessagePackTransportMessage { private TransportMessage _transportMessage; public MessagePackTransportMessage(): this(new TransportMessage()) { } public MessagePackTransportMessage(TransportMessage transportMessage) { this._transportMessage = transportMessage; } public TransportMessage GetTransportMessage() { return _transportMessage; } /// <summary> /// 消息Id。 /// </summary> [Key(0)] public string Id { get { return _transportMessage.Id; } set { _transportMessage.Id = value; } } /// <summary> /// 消息內容。 /// </summary> [Key(1)] public object Content { get { return _transportMessage.Content; } set { _transportMessage.Content = value; } } /// <summary> /// 內容類型。 /// </summary> [Key(2)] public string ContentType { get { return _transportMessage.ContentType; } set { _transportMessage.ContentType = value; } } }
Autofac 是一個依賴注入工具包,比.net Core 原始的依賴注入擁有更完善的功能,中文官方文檔:https://autofaccn.readthedocs.io/zh/latest/index.html
using Autofac; public static class ContainerBuilderExtensions { /// <summary> /// 使用messagepack編碼解碼方式 /// </summary> /// <param name="builder"></param> /// <returns></returns> public static ContainerBuilder UseMessagePackCodec(this ContainerBuilder builder) { builder.RegisterType(typeof(MessagePackTransportMessageCodecFactory)).As(typeof(ITransportMessageCodecFactory)).SingleInstance(); return builder; } }
端到端的測試,同時測試編碼和解碼
using MessagePack; using Microsoft.VisualStudio.TestTools.UnitTesting; [TestClass] public class MessagePackTest { [TestMethod] public void TestCodec() { Person person = new Person { Name = "張宏偉", Age = 18 }; TransportMessage transportMessage = new TransportMessage { Id = "1", ContentType = "Person", Content = person }; MessagePackTransportMessageCodecFactory factory = new MessagePackTransportMessageCodecFactory(); ITransportMessageEncoder encoder = factory.GetEncoder(); ITransportMessageDecoder decoder = factory.GetDecoder(); byte[] vs = encoder.Encode(transportMessage); TransportMessage message =decoder.Decode(vs); Assert.AreEqual(message.Id, "1"); Assert.AreEqual(message.ContentType, "Person"); Assert.AreEqual(((object[])message.Content)[0].ToString(), "張宏偉" ); Assert.AreEqual(((object[])message.Content)[1].ToString(), "18"); } [MessagePackObject] public class Person { [Key(0)] public string Name { get; set; } [Key(1)] public int Age { get; set; } } }