C# protobuf的使用方法

通过.proto文件导出C#支持的.cs类文件

protocolbuffer(以下简称PB)是google 的一种数据交换的格式,它独立于语言,独立于平台。
google 提供了多种语言的实现:java、c#、c++、go 和 python,每一种实现都包含了相应语言的编译器以及库文件。
由于它是一种二进制的格式,比使用xml 进行数据交换快许多。可以把它用于分布式应用之间的数据通信或者异构环境下的数据交换。
作为一种效率和兼容性都很优秀的二进制数据传输格式,可以用于诸如网络传输、配置文件、数据存储等诸多领域。

github上相关开源项目代码:http://pan.baidu.com/s/1eSDSb5o

下面演示如何将protobuf的消息体导出成C#支持的.cs类

首先我们获取到如下.proto文件

package hrv;

option java_package = "com.******.****.***.protobuf";
option java_outer_classname = "RequestProto"; message Request {
extensions 100 to max;
enum Type {
LOGIN = 0;
CHANGE_PASSWORD = 1;
START_SCALE = 2;
STOP_SCALE = 3;
DATA_PPG = 4;
DATA_EP = 5;
DATA_HRV = 6;
DATA_IBI = 7;
MARK_SCALE = 8;
RESOURCE_LIST = 9;
UPDATE_USER_INFO = 10;
GET_SCALE_LIST = 11;
GET_SCALE = 12;
}
required Type type = 1;
optional string timestamp = 2;
}

然后下载导出工具 ProtoGen.exe 下载地址: http://pan.baidu.com/s/1eRIv3oe

通过CMD命令行进入到该目录

使用如下命令行导出.cs文件

protogen.exe  -i:Request.proto    -o:Request.cs

命令解释

protogen -i:test.proto -o:test.cs -ns:UGE.Metadata -p:import=UGE

这句话的意思是, 输入test.proto文件, 给我生成 test.cs 文件, 代码在 namespace UGE.Metadata里, 顺便引用下 using UGE.

可以看到在同目录下生成了一个Request.cs文件,这个文件就是我们想要的cs类文件

Request.cs文件内容如下

 

但是这样一个一个的用命令行导出实在太麻烦,作为会偷懒的程序员,我们要使用更快速的方式批量生成,这个时候我们想到了BAT批处理

echo on

set Path=ProtoGen\protogen.exe

%Path%  -i:Request.proto    -o:OpenAPIModel\Request.cs

%Path%  -i:Response.proto    -o:OpenAPIModel\Response.cs

%Path%  -i:UserInfo.proto    -o:OpenAPIModel\UserInfo.cs

%Path%  -i:LoginReq.proto    -o:OpenAPIModel\LoginReq.cs

%Path%  -i:LoginResp.proto    -o:OpenAPIModel\LoginResp.cs

pause

上面的批处理文件将所有的.proto文件到出成.cs类文件。

或者直接遍历某个文件夹下的所有.prot文件,全部转换

@echo off

set Path=ProtoGen\protogen.exe

for /f "delims=" %%i in ('dir /b proto "proto/*.proto"') do %Path% -i:proto/%%i -o:cs/%%~ni.cs

pause

以上BAT以及demo的下载地址:http://pan.baidu.com/s/1pLtWTy7

搞定!

简介  
Protobuf是google提供的一个开源序列化框架,类似于XML,JSON这样的数据表示语言。 
支持多种编程语言,现:Java、c#、c++、Go 和 Python。 
基于二进制,因此比传统的XML表示高效短小得多 
作为一种效率和兼容性都很优秀的二进制数据传输格式,可以用于诸如网络传输、配置文件、数据存储等诸多领域。 
使用

1、下载地址:http://code.google.com/p/protobuf/downloads/

2、proto文件格式

package 对应于c#中的命名空间 
required 对应类的属性 
optional 创建一个具有默认值的属性,通过[default=XXX]设置默认值,不添加默认为空置。如string默认为“”,int默认为0 
enum 创建枚举 
message 创建自定义类或内部类 
repeated 对应list列表数据 
proto数据类型: 
 
示例:

package test;
message Person {
required string name=1;
required int32 id=2;
optional string email=3 ; enum PhoneType {
MOBILE=0;
HOME=1;
WORK=2;
} message PhoneNumber {
required string number=1;
optional PhoneType type=2 [default=HOME];
} repeated PhoneNumber phone=4;
}

proto文件编辑的命令: 
protogen -i:input.proto -o:output.cs 
protogen -i:input.proto -o:output.xml -t:xml 
protogen -i:input.proto -o:output.cs -p:datacontract -q 
protogen -i:input.proto -o:output.cs -p:observable=true

转换之后的文件:

//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------ // Generated from: input/test.proto
namespace input.test
{
[global::System.Serializable, global::ProtoBuf.ProtoContract(Name=@"Person")]
public partial class Person : global::ProtoBuf.IExtensible
{
public Person() {} private string _name;
[global::ProtoBuf.ProtoMember(1, IsRequired = true, Name=@"name", DataFormat = global::ProtoBuf.DataFormat.Default)]
public string name
{
get { return _name; }
set { _name = value; }
}
private int _id;
[global::ProtoBuf.ProtoMember(2, IsRequired = true, Name=@"id", DataFormat = global::ProtoBuf.DataFormat.TwosComplement)]
public int id
{
get { return _id; }
set { _id = value; }
}
private string _email = "";
[global::ProtoBuf.ProtoMember(3, IsRequired = false, Name=@"email", DataFormat = global::ProtoBuf.DataFormat.Default)]
[global::System.ComponentModel.DefaultValue("")]
public string email
{
get { return _email; }
set { _email = value; }
}
private readonly global::System.Collections.Generic.List<Person.PhoneNumber> _phone = new global::System.Collections.Generic.List<Person.PhoneNumber>();
[global::ProtoBuf.ProtoMember(4, Name=@"phone", DataFormat = global::ProtoBuf.DataFormat.Default)]
public global::System.Collections.Generic.List<Person.PhoneNumber> phone
{
get { return _phone; }
} [global::System.Serializable, global::ProtoBuf.ProtoContract(Name=@"PhoneNumber")]
public partial class PhoneNumber : global::ProtoBuf.IExtensible
{
public PhoneNumber() {} private string _number;
[global::ProtoBuf.ProtoMember(1, IsRequired = true, Name=@"number", DataFormat = global::ProtoBuf.DataFormat.Default)]
public string number
{
get { return _number; }
set { _number = value; }
}
private Person.PhoneType _type = Person.PhoneType.HOME;
[global::ProtoBuf.ProtoMember(2, IsRequired = false, Name=@"type", DataFormat = global::ProtoBuf.DataFormat.TwosComplement)]
[global::System.ComponentModel.DefaultValue(Person.PhoneType.HOME)]
public Person.PhoneType type
{
get { return _type; }
set { _type = value; }
}
private global::ProtoBuf.IExtension extensionObject;
global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing)
{ return global::ProtoBuf.Extensible.GetExtensionObject(ref extensionObject, createIfMissing); }
} [global::ProtoBuf.ProtoContract(Name=@"PhoneType")]
public enum PhoneType
{ [global::ProtoBuf.ProtoEnum(Name=@"MOBILE", Value=0)]
MOBILE = 0, [global::ProtoBuf.ProtoEnum(Name=@"HOME", Value=1)]
HOME = 1, [global::ProtoBuf.ProtoEnum(Name=@"WORK", Value=2)]
WORK = 2
} private global::ProtoBuf.IExtension extensionObject;
global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing)
{ return global::ProtoBuf.Extensible.GetExtensionObject(ref extensionObject, createIfMissing); }
} }

3、proto转化后的.cs文件的序列化和反序列化

首先,将生成的.cs文件复制到自己的项目文件中 
然后添加动态链接库文件protobuf-net.dll(该文件位于下载的proto文件的protobuf-net_r668\ProtoGen目录下) 
然后在程序中引用,相关程序如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ProtoBuf;
using input.test;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
namespace test1
{
class Program
{
static void Main(string[] args)
{
Person p = new Person();
p.name = "zhang san";
p.email = "XXXXX@qq.com";
p.id = 12;
//序列化操作
MemoryStream ms=new MemoryStream();
//BinaryFormatter bm = new BinaryFormatter();
//bm.Serialize(ms, p);
Serializer.Serialize<Person>(ms, p);
byte[] data = ms.ToArray();//length=27 709 //反序列化操作
MemoryStream ms1 = new MemoryStream(data);
// BinaryFormatter bm1 = new BinaryFormatter();
//Person p1= bm.Deserialize(ms1) as Person;
Person p1 = Serializer.Deserialize<Person>(ms1);
Console.ReadKey();
}
}
}
 
 

C#使用protobuf的更多相关文章

  1. python通过protobuf实现rpc

    由于项目组现在用的rpc是基于google protobuf rpc协议实现的,所以花了点时间了解下protobuf rpc.rpc对于做分布式系统的人来说肯定不陌生,对于rpc不了解的童鞋可以自行g ...

  2. Protobuf使用规范分享

    一.Protobuf 的优点 Protobuf 有如 XML,不过它更小.更快.也更简单.它以高效的二进制方式存储,比 XML 小 3 到 10 倍,快 20 到 100 倍.你可以定义自己的数据结构 ...

  3. java netty socket库和自定义C#socket库利用protobuf进行通信完整实例

    之前的文章讲述了socket通信的一些基本知识,已经本人自定义的C#版本的socket.和java netty 库的二次封装,但是没有真正的发表测试用例. 本文只是为了讲解利用protobuf 进行C ...

  4. 在Wcf中应用ProtoBuf替代默认的序列化器

    Google的ProtoBuf序列化器性能的牛逼已经有目共睹了,可以把它应用到Socket通讯,队列,Wcf中,身为dotnet程序员一边期待着不久后Grpc对dotnet core的支持更期待着Wc ...

  5. protobuf的编译安装

    github地址:https://github.com/google/protobuf支持多种语言,有多个语言的版本,本文采用的是在centos7下编译源码进行安装. github上有详细的安装说明: ...

  6. 编译protobuf的jar文件

    1.准备工作 需要到github上下载相应的文件,地址https://github.com/google/protobuf/releases protobuf有很多不同语言的版本,因为我们需要的是ja ...

  7. protobuf学习(2)-相关学习资料

    protobuf官方git地址 protobuf官方英文文档   (你懂的需要FQ) protobuf中文翻译文档 protobuf概述          (官方翻译 推荐阅读) protobuf入门 ...

  8. google protobuf安装与使用

    google protobuf是一个灵活的.高效的用于序列化数据的协议.相比较XML和JSON格式,protobuf更小.更快.更便捷.google protobuf是跨语言的,并且自带了一个编译器( ...

  9. c# (ENUM)枚举组合类型的谷歌序列化Protobuf

    c# (ENUM)枚举组合类型的谷歌序列化Protobuf,必须在序列化/反序列化时加上下面: RuntimeTypeModel.Default[typeof(Alarm)].EnumPassthru ...

  10. dubbox 增加google-gprc/protobuf支持

    好久没写东西了,今年实在太忙,基本都在搞业务开发,晚上来补一篇,作为今年的收官博客.google-rpc 正式发布以来,受到了不少人的关注,这么知名的rpc框架,不集成到dubbox中有点说不过去. ...

随机推荐

  1. CPU Usage (C#) 测试

    注意:算法仅供参考. cpuusage.cs using System; using System.Collections.Generic; using System.Diagnostics; usi ...

  2. Build_Release.bat

    Build_Release.bat @echo off pushd "%~dp0" set tag=Release set PATH="C:\Program Files ...

  3. requirejs打包项目

    例子: https://github.com/AinneShen/requirejsExample 用requirejs为js和css添加版本,项目共用同一个config

  4. ionic2常见问题——修改应用图标及添加启动画面(官方命令行工具自动生成)

    1.项目根目录->resources 分别存放应用图标及添加启动画面,替换成自己的图案既可. 2.这样在命令行中重新运行ionic resources ,就能看到应用图标和名字已经被替换了: 3 ...

  5. LeetCode OJ:Divide Two Integers(两数相除)

    Divide two integers without using multiplication, division and mod operator. If it is overflow, retu ...

  6. cocos2dx lua 热加载实现

    [Q]原创 2015-08-30 在公司使用cocos2dx+lua 开发游戏有一段时间了,刚好lua的热更新交给我负责.以前热更新的lua脚本大部分都是在下载之后加载.最近策划又有新需求,需要在游戏 ...

  7. [转]MFC 调用 printf 输出

    摘自:http://blog.csdn.net/miyunhong/article/details/6704121 #include <io.h> #include <fcntl.h ...

  8. 洛谷 P2920 [USACO08NOV]时间管理Time Management

    传送门 题目大意: 每个工作有截至时间和耗费时间,n个工作求最小开始时间. 题解: 贪心 从n-1安排,让结束时间尽量的晚. 注意:优先级 cout<<st<0?-1:st;  (X ...

  9. Spring aop 简单示例

    简单的记录一下spring aop的一个示例 基于两种配置方式: 基于xml配置 基于注解配置 这个例子是模拟对数据库的更改操作添加事物 其实并没有添加,只是简单的输出了一下记录 首先看下整个例子的目 ...

  10. ArcGIS破解配置及oracle文件配置

    1.破解配置 2.oracle文件配置