欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

(一)ASP.Net Core 分布式通信----序列化

程序员文章站 2022-05-18 15:20:51
1. .Net Core的序列化方式 1.1 json.Net 常用的工具包,如Newtonsoft.Json, 它是基于json格式的序列化和反序列化的组件 json.net 有以下优点: 侵入性:可以不添加attribute,就能进行序列化操作 灵活性:可以灵活性配置,比如允许被序列化的成员自定 ......

1. .net core的序列化方式

1.1 json.net

常用的工具包,如newtonsoft.json, 它是基于json格式的序列化和反序列化的组件

json.net 有以下优点:

       侵入性:可以不添加attribute,就能进行序列化操作

       灵活性:可以灵活性配置,比如允许被序列化的成员自定义名字,屏蔽的非序列化属性成员

       可读性: 数据格式比较简单, 易于读写

       依赖性:可以序列化成jobject,无需依赖对象进行序列化和泛型化。

1.2 protobuf

它是基于二进制格式的序列化和反序列化的组件

protobuf 有以下优点:

     性能高 : 序列化后体积相比json和xml很小,适合rpc二进制传输
   跨语言:支持跨平台多语言
        兼容性:消息格式升级和兼容性还不错
        速度快 :序列化反序列化速度很快,快于json的处理速度

1.3 messagepack

它是基于二进制格式的序列化和反序列化的组件

messagepack有以下优点:

      性能高:序列化后体积相比json和xml很小,适合rpc二进制传输
   跨语言:支持跨平台多语言
        兼容性:消息格式升级和兼容性还不错
        速度快 :序列化反序列化速度很快,快于json的处理速度

messagepack不管是小数据量还是大数据量都保持比较稳定的性能,本文中使用messagepack序列化方式。

2. 项目编码及设计模式

 如下是文件结构:

(一)ASP.Net Core 分布式通信----序列化

 

2.1 工厂模式

抽象类

    /// <summary>
    /// 一个抽象的传输消息编解码器工厂。
    /// </summary>
    public interface itransportmessagecodecfactory
    {
        /// <summary>
        /// 获取编码器。
        /// </summary>
        /// <returns>编码器实例。</returns>
        itransportmessageencoder getencoder();

        /// <summary>
        /// 获取解码器。
        /// </summary>
        /// <returns>解码器实例。</returns>
        itransportmessagedecoder getdecoder();
    }

 

    /// <summary>
    /// 编码器
    /// </summary>
    public interface itransportmessageencoder
    {
        byte[] encode(transportmessage message);
    }

 

    /// <summary>
    /// 解码器
    /// </summary>
    public interface itransportmessagedecoder
    {
        transportmessage decode(byte[] data);
    }

 

实现类

   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
    }

 

    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
    }

 

    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
    }

 

2.2 装饰器模式

    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; }
    }

 

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; }
        }
    }

 

2.3 依赖注入

 

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;
        }
    }

 

 2.4 单元测试

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; }
        }
    }