我有一个序列化对象并通过网络发送它的程序:

TcpClient client = new TcpClient();
client.ReceiveTimeout = 10000;
client.SendTimeout = 10000;
IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8888);
client.Connect(serverEndPoint);

BinaryFormatter binaryformatter = new BinaryFormatter();

NetworkStream networkStream = client.GetStream();
if (networkStream.CanWrite)
{
    binaryformatter.Serialize(networkStream, kort);
}


另一方面,我接收并反序列化代码如下:

TcpClient tcpClient = (TcpClient)client;
tcpClient.SendTimeout = 10000;
tcpClient.ReceiveTimeout = 10000;
NetworkStream clientStream = tcpClient.GetStream();
try
{
    if (clientStream.CanRead)
    {
        BinaryFormatter binaryformatter = new BinaryFormatter();
        binaryformatter.Binder = new AllowAllAssemblyVersionsDeserializationBinder();

        Kort tempkort = (Kort)binaryformatter.Deserialize(clientStream);
        SetImage(tempkort);
    }
}
catch (SerializationException e)
{
    MessageBox.Show("Failed to deserialize. Reason: " + e.Message);
    throw;
}
finally
{
    clientStream.Close();
    tcpClient.Close();
}


但是当我反序列化时,我遇到了有关程序集缺失的错误:


  “在Server.exe中发生了System.Runtime.Serialization.SerializationException类型的未处理异常。其他信息:无法找到程序集'客户端,版本= 1.0.0.0,区域性=中性,PublicKeyToken =空”。


我用这个解决了

sealed class AllowAllAssemblyVersionsDeserializationBinder : SerializationBinder
{
    public override Type BindToType(string assemblyName, string typeName)
    {
        String currentAssembly = Assembly.GetExecutingAssembly().FullName;

        // In this case we are always using the current assembly
        typeName = "Server.Kort";
        assemblyName = currentAssembly;

        // Get the type using the typeName and assemblyName
        Type typeToDeserialize = Type.GetType(String.Format("{0}, {1}",
            typeName, assemblyName));

        return typeToDeserialize;
    }
}


但是,现在我尝试这样做,我不断收到一条错误消息:


  “类型Server.Kort的对象不能转换为类型Server.Kort+kortvalör。”


而且我不知道如何解决它。

最佳答案

发送方的类Kort必须包含一个称为enum的嵌套类型(也许是kortvalör?)的实例。而且,由于BinaryFormatter序列化了公共和私有字段而不是属性,因此嵌套类型对于外界可能是完全不可见的,但是仍然可以序列化。

例如,我能够使用具有以下类的活页夹来再现您的异常"Object of type Server.Kort cannot be converted to type Server.Kort+kortvalör"

[Serializable]
public class Kort
{
    // Private enum that is invisible to the outside world.
    enum kortvalör
    {
        Zero,
        One,
        Two,
        Three
    }

    kortvalör valör = kortvalör.Three;

    public int Value
    {
        get
        {
            return (int)valör;
        }
        set
        {
            // Check to make sure the incoming value is in a valid range.
            var newvalör = (kortvalör)value;
            if (Enum.IsDefined(typeof(kortvalör), newvalör))
                valör = newvalör;
            else
                valör = default(kortvalör);
        }
    }
}


反序列化上述类时,将两次调用您的活页夹,一次是使用typeName表示Kort,然后是一次使用类型名"MyClientNamespace.Kort+kortvalör"。由于您的活页夹忽略传入的typeName并返回typeof(Kort),因此失败。

您可以选择几种方法来解决此问题:


将类Kort提取到共享的DLL中,并将其与发送和接收应用程序链接。然后问题就解决了。
在发送和接收应用程序中创建Kort引用的所有类型的重复项(包括私有嵌套类型),并在更智能的SerializationBinder版本中适当地重新映射类型名称。文章Advanced Binary Serialization: Deserializing an Object Into a Different Type Than the One It was Serialized Into中有一个示例。
考虑使用其他序列化属性而不是私有字段的序列化格式。 BSON是一种选择。 Protobuf-net是另一个。

关于c# - 用binaryformatter反序列化,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/30196506/

10-11 06:16