Skip to content

使用 Thrifty 定义 thrift 结构

Anders Xiao edited this page Dec 1, 2017 · 1 revision

如何使用 Thrifty 定义 thrift 结构(struct)


Thrifty 通过 ThriftStructAttribute、ThriftFieldAttribute 特性来描述一个结构。

任何的 thrift 标准 IDL 中的 struct 都可以通过特性使用 C# 代码来定义:

使用常规定义

考虑如下 IDL:

enum EnOpType {
  CMD_OK = 0,
  CMD_EXIT = 2001, 
  CMD_ADD = 2002 
}

struct user {
  1: required i32 userId;
  2: required string userName;
  3: optional EnOpType cmd_code;
  4: optional string language = “english”;
  5: list<i64> ID;
}

使用 Thrifty 来定义可表示为

public enum EnOpType
{
   CMD_OK = 0,
   CMD_EXIT = 2001,
   CMD_ADD = 2002
}

[ThriftStruct("user")]
public class User
{
  [ThriftField(1, Name = "userId")]
  public int UserId { get; set;}

  [ThriftField(2, Name = "userName")]
  public string UserName { get; set;}
 
  [ThriftField(3, Name = "cmd_code"]
  public EnOpType? CmdCode { get; set;}

  [ThriftField(4, Name = "language")]
  public string Language { get; set;} = "english";

  [ThriftField(5)] //ThriftFieldAttribute 的 Name 并不是必须赋值的,默认使用属性名
  public IList<long> ID { get; set;}
}

注意 ThriftStructAttribute 默认使用类型作为 Name, 也可以显示指定,同样,的 ThriftFieldAttribute 并不是必须赋值的,默认使用属性名

使用构造函数

如上例所属的 User 类型,现在考虑如果 UserId 和 UserName 为只读,只允许通过构造函数传入,可以通过如下定义实现:

[ThriftStruct("user")]
public class User
{
  public User([ThriftField(1)]string userId, [ThriftField(2)]user name)
  {
    this.UserId = userId,
    this.UserName = name
  }

  [ThriftField(1, Name = "userId")]
  public int UserId { get;}

  [ThriftField(2, Name = "userName")]
  public string UserName { get;}
 
  [ThriftField(3, Name = "cmd_code"]
  public EnOpType? CmdCode { get; set;}

  [ThriftField(4, Name = "language")]
  public string Language { get; set;} = "english";

  [ThriftField(5)] //ThriftFieldAttribute 的 Name 并不是必须赋值的,默认使用属性名
  public IList<long> ID { get; set;}
}

说明,构造函数中 ThriftFieldAttribute 用来告知 Thrifty 反序列化对象时使用哪个字段来传递参数,参数上的 ThriftFieldAttribute 并不要求 Name 对应,只要求数字(field id)和属性对应即可。

C# 类继承

ThriftFieldAttribute 描述的字段可以被子类继承,但 ThriftStructAttribute 并不会对继承类有效 。 使用继承类时,要求子类的 ThriftFieldAttribute 特性上的 id 必须在整个继承链上唯一

考虑如下 C# 类型,继承自上例中的 User 类:

[ThriftStruct("AgeUser")]
public class User2 : User
{
  public User([ThriftField(1)]string userId, [ThriftField(2)]user name)
    : base(userId, name)
  {
    this.UserId = userId,
    this.UserName = name
  }
  
  [ThriftField(6, Name = "age")]
  public int Age{ get; set;}

}

User2 对应 IDL 如下:

struct AgeUser {
  1: required i32 userId;
  2: required string userName;
  3: optional EnOpType cmd_code;
  4: optional string language = “english”;
  5: list<i64> ID;
  6: required i32 age;
}