You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

C#中使用BinaryFormatter解析程序集失败问题求助

解决Neo智能合约中BinaryFormatter序列化失败的问题

嘿,我完全懂你碰到的麻烦——在Neo智能合约里用BinaryFormatter来序列化结构体根本走不通,这可不是代码写错了,而是Neo的合约运行环境有严格的限制导致的。

为什么BinaryFormatter用不了?

Neo智能合约是运行在NeoVM这个轻量级虚拟机上的,它只支持.NET标准库的极小子集,像System.Runtime.Serialization.Formatters.Binary这类依赖完整CLR运行时、涉及反射和程序集动态加载的组件,都是被明确禁用的。这就是你遇到“解析程序集失败”错误的核心原因。

替代方案:手动实现序列化/反序列化

既然框架自带的序列化工具用不了,我们可以针对结构体的字段手动处理字节流的读写,这种方式不仅符合NeoVM的环境要求,还更高效。下面给你举个具体的例子:

假设你的Driver结构体是这样的:

public struct Driver
{
    public string Name;
    public BigInteger Age;
    public byte[] LicenseId;
}

序列化方法

把结构体的每个字段依次转成字节数组并拼接,同时记录每个字段的长度(方便反序列化时读取):

public static byte[] SerializeDriver(Driver driver)
{
    using (MemoryStream ms = new MemoryStream())
    {
        // 处理字符串类型:先写长度,再写内容
        byte[] nameBytes = System.Text.Encoding.UTF8.GetBytes(driver.Name);
        ms.Write(BitConverter.GetBytes((ushort)nameBytes.Length), 0, 2);
        ms.Write(nameBytes, 0, nameBytes.Length);
        
        // 处理BigInteger类型:转成字节数组后记录长度再写入
        byte[] ageBytes = driver.Age.ToByteArray();
        ms.Write(BitConverter.GetBytes((ushort)ageBytes.Length), 0, 2);
        ms.Write(ageBytes, 0, ageBytes.Length);
        
        // 处理byte数组类型:同样先写长度再写内容
        ms.Write(BitConverter.GetBytes((ushort)driver.LicenseId.Length), 0, 2);
        ms.Write(driver.LicenseId, 0, driver.LicenseId.Length);
        
        return ms.ToArray();
    }
}

反序列化方法

按照序列化时的顺序,依次读取每个字段的长度和内容,重新组装成结构体:

public static Driver DeserializeDriver(byte[] data)
{
    Driver driver = new Driver();
    using (MemoryStream ms = new MemoryStream(data))
    {
        byte[] lenBuffer = new byte[2];
        
        // 读取Name字段
        ms.Read(lenBuffer, 0, 2);
        ushort nameLen = BitConverter.ToUInt16(lenBuffer, 0);
        byte[] nameBytes = new byte[nameLen];
        ms.Read(nameBytes, 0, nameLen);
        driver.Name = System.Text.Encoding.UTF8.GetString(nameBytes);
        
        // 读取Age字段
        ms.Read(lenBuffer, 0, 2);
        ushort ageLen = BitConverter.ToUInt16(lenBuffer, 0);
        byte[] ageBytes = new byte[ageLen];
        ms.Read(ageBytes, 0, ageLen);
        driver.Age = new BigInteger(ageBytes);
        
        // 读取LicenseId字段
        ms.Read(lenBuffer, 0, 2);
        ushort licenseLen = BitConverter.ToUInt16(lenBuffer, 0);
        driver.LicenseId = new byte[licenseLen];
        ms.Read(driver.LicenseId, 0, licenseLen);
        
        return driver;
    }
}

额外提醒

在Neo智能合约开发中,一定要记住:避免使用依赖完整.NET框架的类库,优先使用Neo.SmartContract.Framework提供的工具类,或者像上面这样手动实现核心逻辑。合约环境的资源和功能都有限制,轻量化的实现才是正确的方向。

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

火山引擎 最新活动