微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

是否有一些高性能可以替代.NET5中的BinaryFormatter?

如何解决是否有一些高性能可以替代.NET5中的BinaryFormatter?

在.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,bytes.Length);
            memStream.Seek(0,SeekOrigin.Begin);
            var obj = binForm.Deserialize(memStream);
            return (T)obj;
        }
    }

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

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

那么有什么简单但高性能方法可以替换BinaryFormatter?

解决方法

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

代码几乎完全相同,并且该项目在GitHub上(目前)有2200万次下载和3.2k星,因此享有盛誉。它非常快速,并且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,arrBytes.Length);
        stream.Seek(0,SeekOrigin.Begin);

        return Serializer.Deserialize<T>(stream);
    }
}

我确实必须向序列化的类添加属性。它仅用[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;}
}

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

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

<PropertyGroup>
    <TargetFramework>net5.0</TargetFramework>
    <EnableUnsafeBinaryFormatterSerialization>true</EnableUnsafeBinaryFormatterSerialization>
</PropertyGroup>

...但这是一个坏主意。 BinaryFormatter负责.NET的许多历史漏洞,因此无法修复。在将来的.NET版本中,它可能会变得完全不可用,因此替换它是正确的选择。

,

如果您使用 .NET Core 5 或更高版本,您可以像这样使用新的 System.Text.Json.JsonSerializer.Serialize 和 System.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,};
    }
}
,

在.NET Core 5中可以使用它:

只需添加

<EnableUnsafeBinaryFormatterSerialization>true</EnableUnsafeBinaryFormatterSerialization>

对于这样的项目:

<PropertyGroup>
    <TargetFramework>net5.0</TargetFramework>
    <EnableUnsafeBinaryFormatterSerialization>true</EnableUnsafeBinaryFormatterSerialization>
</PropertyGroup>

我相信它会起作用。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?