You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于反射实现对象反序列化:遍历字段从SerializationInfo取值

用反射实现对象的反序列化逻辑

嘿,我懂你现在的需求——之前手动写反序列化构造函数,每次加新字段都要改代码,太麻烦了对吧?用反射来自动遍历字段赋值确实能省不少事,我来给你一步步讲怎么实现:

核心思路

通过反射获取类的所有字段,逐个从SerializationInfo中取出对应值并赋值给当前实例,同时跳过不需要序列化的字段。

具体实现步骤

  • 首先确保你的类标记了[Serializable]特性,并且实现了ISerializable接口(如果是自定义序列化的话):
    [Serializable]
    public class SKA_MAP : ISerializable
    {
        // 你的字段定义
    }
    
  • 在反序列化构造函数中,用反射获取字段并处理:
    1. 获取类的所有实例字段(包括私有字段,可根据需求调整绑定标志):
      var fields = typeof(SKA_MAP).GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
      
    2. 遍历字段,跳过[NonSerialized]标记的字段,从SerializationInfo取值并赋值:
      foreach (var field in fields)
      {
          // 跳过不需要序列化的字段
          if (field.GetCustomAttribute<NonSerializedAttribute>() != null)
              continue;
          
          // 检查SerializationInfo中是否存在该字段,避免报错
          if (info.MemberNames.Contains(field.Name))
          {
              try
              {
                  var value = info.GetValue(field.Name, field.FieldType);
                  field.SetValue(this, value);
              }
              catch (Exception ex)
              {
                  // 可根据需求添加异常处理,比如日志
                  Console.WriteLine($"反序列化字段 {field.Name} 失败: {ex.Message}");
              }
          }
      }
      

完整示例代码

[Serializable]
public class SKA_MAP : ISerializable
{
    // 示例字段
    public int MapId;
    private string MapName;
    [NonSerialized]
    public string TemporaryData; // 这个字段不会被序列化/反序列化

    // 反序列化构造函数
    public SKA_MAP(SerializationInfo info, StreamingContext ctxt)
    {
        // 获取所有实例字段(公共+私有)
        var fields = typeof(SKA_MAP).GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
        
        foreach (var field in fields)
        {
            // 跳过NonSerialized字段
            if (field.GetCustomAttribute<NonSerializedAttribute>() != null)
                continue;
            
            if (info.MemberNames.Contains(field.Name))
            {
                try
                {
                    var fieldValue = info.GetValue(field.Name, field.FieldType);
                    field.SetValue(this, fieldValue);
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"处理字段 {field.Name} 出错: {ex.Message}");
                }
            }
        }
    }

    // 序列化方法,同样用反射保持逻辑一致
    public void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        var fields = typeof(SKA_MAP).GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
        foreach (var field in fields)
        {
            if (field.GetCustomAttribute<NonSerializedAttribute>() != null)
                continue;
            info.AddValue(field.Name, field.GetValue(this));
        }
    }
}

注意事项

  • 绑定标志调整:如果只需要处理公共字段,去掉BindingFlags.NonPublic即可;如果要包含静态字段,添加BindingFlags.Static(不过反序列化一般用实例字段)。
  • 字段名一致性:序列化和反序列化时的字段名必须完全匹配,用反射实现GetObjectData能保证这一点,避免手动写错。
  • 继承处理:如果你的类继承自其他可序列化类,记得在构造函数开头调用base(info, ctxt);,否则基类的字段无法被反序列化。

内容的提问来源于stack exchange,提问作者tobeypeters

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 11:11:18