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

C#使用BinaryFormatter序列化时第三方Point类无Serializable属性如何解决

解决方案

你可以通过以下几种方式解决无法给第三方类型加[Serializable]特性的序列化问题:

方案1:为ServerItem实现ISerializable接口自定义序列化逻辑

自己控制ServerItem的序列化过程,手动存储Point的坐标值,反序列化时再重建Point对象:

[Serializable]
public class ServerItem : ISerializable
{
    public string Id { get; }
    public string Name => this.info.Name;
    public bool IsOptimal { get; set; }
    public string Region => this.info.Region;
    public string City => this.info.Description;
    public Point? Location { get; }

    // 反序列化用的构造函数
    protected ServerItem(SerializationInfo info, StreamingContext context)
    {
        Id = info.GetString(nameof(Id));
        IsOptimal = info.GetBoolean(nameof(IsOptimal));
        // 反序列化Point坐标
        if (info.GetBoolean("HasLocation"))
        {
            double x = info.GetDouble("LocationX");
            double y = info.GetDouble("LocationY");
            Location = new Point(x, y);
        }
        // 这里补充info字段的反序列化逻辑,根据你实际的info类型处理
    }

    // 自定义序列化逻辑
    public void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        info.AddValue(nameof(Id), Id);
        info.AddValue(nameof(IsOptimal), IsOptimal);
        // 单独存Point的坐标
        info.AddValue("HasLocation", Location.HasValue);
        if (Location.HasValue)
        {
            info.AddValue("LocationX", Location.Value.X);
            info.AddValue("LocationY", Location.Value.Y);
        }
        // 这里补充info字段的序列化逻辑,根据你实际的info类型处理
    }

    // 你原来的其他构造函数、逻辑保留
}

方案2:新增可序列化的坐标存储字段,将Point改为计算属性

无需修改序列化逻辑,只需要调整ServerItem的字段设计:

[Serializable]
public class ServerItem
{
    public string Id { get; }
    public string Name => this.info.Name;
    public bool IsOptimal { get; set; }
    public string Region => this.info.Region;
    public string City => this.info.Description;
    
    // 用基础类型存储坐标,基础类型天然支持序列化
    private double? _locationX;
    private double? _locationY;
    // Point改为计算属性,不参与默认序列化
    public Point? Location => _locationX.HasValue ? new Point(_locationX.Value, _locationY.Value) : null;

    // 你原来的构造函数中,给Location赋值的逻辑改成给两个字段赋值
    public ServerItem(/* 你的其他参数 */ Point? location)
    {
        if (location.HasValue)
        {
            _locationX = location.Value.X;
            _locationY = location.Value.Y;
        }
    }

    // 其他原有逻辑保留
}

方案3:为Point类型注册序列化代理

不需要修改ServerItem类,只需要调整你的序列化方法,给BinaryFormatter指定Point的序列化规则:
首先实现Point的序列化代理类:

public class PointSerializationSurrogate : ISerializationSurrogate
{
    public void GetObjectData(object obj, SerializationInfo info, StreamingContext context)
    {
        Point point = (Point)obj;
        info.AddValue("X", point.X);
        info.AddValue("Y", point.Y);
    }

    public object SetObjectData(object obj, SerializationInfo info, StreamingContext context, ISurrogateSelector selector)
    {
        double x = info.GetDouble("X");
        double y = info.GetDouble("Y");
        return new Point(x, y);
    }
}

然后修改你的序列化方法,注册代理:

public static byte[] Serialize(object obj)
{
    try
    {
        byte[] bytes;
        IFormatter formatter = new BinaryFormatter();
        
        // 注册Point的序列化代理
        SurrogateSelector surrogateSelector = new SurrogateSelector();
        surrogateSelector.AddSurrogate(typeof(Point), new StreamingContext(StreamingContextStates.All), new PointSerializationSurrogate());
        formatter.SurrogateSelector = surrogateSelector;

        using (MemoryStream stream = new MemoryStream())
        {
            formatter.Serialize(stream, obj);
            bytes = stream.ToArray();
        }
        return bytes;
    }
    catch
    {
        return null;
    }
}
// 反序列化方法也要加上同样的代理注册逻辑

方案4:替换序列化方案(更推荐)

BinaryFormatter已经被微软标记为不安全API,高版本.NET默认禁用,存在远程代码执行风险。你可以换成System.Text.Json、Newtonsoft.Json或者Protobuf.NET这类序列化库,这类库不需要类型标记[Serializable]特性,只要可以访问到公共属性就可以直接序列化,改造成本更低,安全性和性能也更好。


内容的提问来源于stack exchange,提问作者Янислав Колодочка

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 19:09:01