---
id: serializationselector
title: 序列化选择器
---

## 一、说明

从下图（图片来源[网络](https://www.jianshu.com/p/7d6853140e13)）可以看出，序列化是RPC中至关重要的一个环节，可以说，序列化的优劣，会很大程度的影响RPC调用性能。

<img src={require('@site/static/img/docs/serializationselector-1.png').default} />

## 二、支持的序列化

在TouchRpc中，内置了四种序列化方式，分别为`FastBinary`、`Json`、`Xml`、`SystemBinary`。这四种方式的特点，就是其序列化的特点。

|  | FastBinary | Json | Xml | SystemBinary |
| --- | --- | --- | --- | --- |
| 特点 | 序列化方式速度快，数据量小，但是兼容的数据格式也比较有限。仅支持基础类型、自定义实体类、数组、List、字典 | 兼容性好，可读性强，但是受字符串影响，性能不出众，且数据量受限制 | 兼容性一般，可读性强，同样受字符串影响，性能不出众，且数据量受限制 | 序列化速度快。但是兼容性低。且要求类必须一致，不然需要重新指定图根。 |

## 三、使用预设序列化

在TouchRpc中，选择序列化是非常简单的，且序列化方式完全由`调用端`决定。
在实际的调用中，通过`InvokeOption`的参数指定。

实际上，只需要传入相关参数即可。

```csharp
InvokeOption invokeOption = new InvokeOption() //InvokeOption是结构体，所以成员必须全部初始化。
{
    FeedbackType = FeedbackType.WaitInvoke,
    Timeout = 1000 * 10
};
;
invokeOption.SerializationType = SerializationType.FastBinary;
//invokeOption.SerializationType = Serialization.SerializationType.Json;
//invokeOption.SerializationType = Serialization.SerializationType.Xml;
string returnString = client.Invoke<string>("TestOne", invokeOption, "10");
```


## 四、自定义序列化

### 4.1 定义自定义序列化器

想要实现自定义序列化，必须通过重写序列化选择器，实现`SerializeParameter`和`DeserializeParameter`函数。

下列代码将以`MemoryPack`序列化作为示例，并且保留了预设序列化。

```csharp
public class MemoryPackSerializationSelector:DefaultSerializationSelector
{
    public override byte[] SerializeParameter(SerializationType serializationType, object parameter)
    {
        if ((byte)serializationType == 4)
        {
           return MemoryPackSerializer.Serialize(parameter.GetType(),parameter);
        }
        return base.SerializeParameter(serializationType, parameter);
    }

    public override object DeserializeParameter(SerializationType serializationType, byte[] parameterBytes, Type parameterType)
    {
        if ((byte)serializationType == 4)
        {
            if (parameterBytes==null)
            {
                return default;
            }
            return MemoryPackSerializer.Deserialize(parameterType,parameterBytes);
        }
        return base.DeserializeParameter(serializationType, parameterBytes, parameterType);
    }
}
```

### 4.2 使用

必须在`服务器`和`客户端`的**Config配置**中设置解析器。

```csharp
var config = new TouchSocketConfig()//配置
    .SetSerializationSelector(new MemoryPackSerializationSelector());
```

然后，因为赋值时是`SerializationType`的枚举类型，所以执行强制类型转换即可。

```csharp
InvokeOption invokeOption = new InvokeOption()
{
    FeedbackType = FeedbackType.WaitInvoke,
    SerializationType = (SerializationType)4,
    Timeout = 1000 * 10
};

var msg = client.Login(new LoginModel() { Account = "Account", Password = "Password" }, invokeOption);
```

:::tip 提示

因为使用的是`MemoryPack`序列化，所以最好将Rpc的所有参数声明在单独的程序集中。这样客户端与服务器项目都可以直接引用。

:::  

[序列化选择器示例代码](https://gitee.com/RRQM_Home/TouchSocket/tree/master/examples/TouchRpc%E7%AE%80%E5%8D%95%E7%A4%BA%E4%BE%8B/%E5%BA%8F%E5%88%97%E5%8C%96%E9%80%89%E6%8B%A9%E5%99%A8)
