有没有一种高性能的方法来替换 .NET5 中的 BinaryFormatter?

Fai*_*air 7 binaryformatter .net-5

在 .NET5 之前,我们通过以下代码序列化/反序列化字节/对象:

    private static byte[] StructToBytes<T>(T t)
    {
        using (var ms = new MemoryStream())
        {
            var bf = new BinaryFormatter();
            bf.Serialize(ms, t);
            return ms.ToArray();
        }
    }

    private static T BytesToStruct<T>(byte[] bytes)
    {
        using (var memStream = new MemoryStream())
        {
            var binForm = new BinaryFormatter();
            memStream.Write(bytes, 0, bytes.Length);
            memStream.Seek(0, SeekOrigin.Begin);
            var obj = binForm.Deserialize(memStream);
            return (T)obj;
        }
    }
Run Code Online (Sandbox Code Playgroud)

但出于安全原因,BinaryFormatter 将被删除:

https://docs.microsoft.com/zh-cn/dotnet/standard/serialization/binaryformatter-security-guide

那么有没有一些简单但高性能的方法来代替 BinaryFormatter 呢?

Chi*_*obe 16

如果您使用 .NET Core 5 或更高版本,则可以使用新版本System.Text.Json.JsonSerializer.SerializeSystem.Text.Json.JsonSerializer.Deserialize如下所示:

public static class Binary
{
    /// <summary>
    /// Convert an object to a Byte Array.
    /// </summary>
    public static byte[] ObjectToByteArray(object objData)
    {
        if (objData == null)
            return default;

       return Encoding.UTF8.GetBytes(JsonSerializer.Serialize(objData, GetJsonSerializerOptions()));
    }

    /// <summary>
    /// Convert a byte array to an Object of T.
    /// </summary>
    public static T ByteArrayToObject<T>(byte[] byteArray)
    {
        if (byteArray == null || !byteArray.Any())          
            return default;
            
        return JsonSerializer.Deserialize<T>(byteArray, GetJsonSerializerOptions());
    }

    private static JsonSerializerOptions GetJsonSerializerOptions()
    {
        return new JsonSerializerOptions()
        {
            PropertyNamingPolicy = null,
            WriteIndented = true,
            AllowTrailingCommas = true,
            DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
        };
    }
}
Run Code Online (Sandbox Code Playgroud)


Bri*_*Kay 9

在我最近从 .NET Core 3.1 迁移到 .NET 5 的项目中,我用 Protobuf-net 替换了我们的 BinarySerializer 代码:https : //github.com/protobuf-net/protobuf-net

代码几乎完全相同,并且该项目在 GitHub 上(目前)有 2200 万次下载和 320 万颗星,享有盛誉。它非常快,并且没有围绕 BinarySerializer 的安全包袱。

这是我的 byte[] 序列化类:

public static class Binary
{
    /// <summary>
    /// Convert an object to a Byte Array, using Protobuf.
    /// </summary>
    public static byte[] ObjectToByteArray(object obj)
    {
        if (obj == null)
            return null;

        using var stream = new MemoryStream();

        Serializer.Serialize(stream, obj);

        return stream.ToArray();
    }

    /// <summary>
    /// Convert a byte array to an Object of T, using Protobuf.
    /// </summary>
    public static T ByteArrayToObject<T>(byte[] arrBytes)
    {
        using var stream = new MemoryStream();

        // Ensure that our stream is at the beginning.
        stream.Write(arrBytes, 0, arrBytes.Length);
        stream.Seek(0, SeekOrigin.Begin);

        return Serializer.Deserialize<T>(stream);
    }
}
Run Code Online (Sandbox Code Playgroud)

我确实必须向我序列化的类添加属性。它只用 [Serializable] 装饰,虽然我知道 Protobuf 可以处理很多常见的装饰,但那个不起作用。从github上的例子:

[ProtoContract]
class Person {
    [ProtoMember(1)]
    public int Id {get;set;}
    [ProtoMember(2)]
    public string Name {get;set;}
    [ProtoMember(3)]
    public Address Address {get;set;}
}

[ProtoContract]
class Address {
    [ProtoMember(1)]
    public string Line1 {get;set;}
    [ProtoMember(2)]
    public string Line2 {get;set;}
}
Run Code Online (Sandbox Code Playgroud)

就我而言,我正在 Redis 中缓存内容,并且效果很好。

也可以在您的 .csproject 文件中重新启用它:

<PropertyGroup>
    <TargetFramework>net5.0</TargetFramework>
    <EnableUnsafeBinaryFormatterSerialization>true</EnableUnsafeBinaryFormatterSerialization>
</PropertyGroup>
Run Code Online (Sandbox Code Playgroud)

……但这是个坏主意。BinaryFormatter 对 .NET 的许多历史漏洞负责,而且无法修复。它可能会在 .NET 的未来版本中完全不可用,因此更换它是正确的做法。

  • 不要因上述[SO问题](/sf/ask/3135958521/ -数据输出)。Microsoft 提供的“BinaryFormatter”替代方案(“XmlSerializer”和“System.Text.JSON”)同样容易受到窥探。所有这些都可以通过加密流来缓解。`BinaryFormatter` 的漏洞要严重得多。格式错误的二进制数据源可能会导致任何问题,从崩溃到成为恶意软件的载体。 (2认同)

小智 0

有一个选项可以在 .NET Core 5 中使用它:

只需添加

<EnableUnsafeBinaryFormatterSerialization>true</EnableUnsafeBinaryFormatterSerialization>
Run Code Online (Sandbox Code Playgroud)

对于这样的项目:

<PropertyGroup>
    <TargetFramework>net5.0</TargetFramework>
    <EnableUnsafeBinaryFormatterSerialization>true</EnableUnsafeBinaryFormatterSerialization>
</PropertyGroup>
Run Code Online (Sandbox Code Playgroud)

我相信它会起作用。


归档时间:

查看次数:

3916 次

最近记录:

4 年,11 月 前