Tôi có 2 ứng dụng nối mạng sẽ gửi các tin nhắn protobuf-net tuần tự cho nhau. Tôi có thể tuần tự hóa các đối tượng và gửi chúng, tuy nhiên, Tôi không thể tìm ra cách để deserialize các byte nhận được.Deserialize loại không xác định với protobuf-net
Tôi đã cố gắng deserialize với điều này và nó đã thất bại với một NullReferenceException.
// Where "ms" is a memorystream containing the serialized
// byte array from the network.
Messages.BaseMessage message =
ProtoBuf.Serializer.Deserialize<Messages.BaseMessage>(ms);
Tôi đang chuyển tiêu đề trước các byte được tuần tự hóa chứa ID loại thông báo mà tôi có thể sử dụng trong câu lệnh chuyển đổi khổng lồ để trả về loại sublcass được mong đợi. Với khối bên dưới, tôi nhận được lỗi: System.Reflection.TargetInvocationException ---> System.NullReferenceException.
//Where "ms" is a memorystream and "messageType" is a
//Uint16.
Type t = Messages.Helper.GetMessageType(messageType);
System.Reflection.MethodInfo method =
typeof(ProtoBuf.Serializer).GetMethod("Deserialize").MakeGenericMethod(t);
message = method.Invoke(null, new object[] { ms }) as Messages.BaseMessage;
Dưới đây là các chức năng tôi sử dụng để gửi tin nhắn qua mạng:
internal void Send(Messages.BaseMessage message){
using (System.IO.MemoryStream ms = new System.IO.MemoryStream()){
ProtoBuf.Serializer.Serialize(ms, message);
byte[] messageTypeAndLength = new byte[4];
Buffer.BlockCopy(BitConverter.GetBytes(message.messageType), 0, messageTypeAndLength, 0, 2);
Buffer.BlockCopy(BitConverter.GetBytes((UInt16)ms.Length), 0, messageTypeAndLength, 2, 2);
this.networkStream.Write(messageTypeAndLength);
this.networkStream.Write(ms.ToArray());
}
}
này lớp, với lớp cơ sở, tôi serializing:
[Serializable,
ProtoContract,
ProtoInclude(50, typeof(BeginRequest))]
abstract internal class BaseMessage
{
[ProtoMember(1)]
abstract public UInt16 messageType { get; }
}
[Serializable,
ProtoContract]
internal class BeginRequest : BaseMessage
{
[ProtoMember(1)]
public override UInt16 messageType
{
get { return 1; }
}
}
Đã sửa lỗi sử dụng đề xuất của Marc Gravell. Tôi đã loại bỏ thuộc tính ProtoMember khỏi các thuộc tính chỉ đọc. Cũng chuyển sang sử dụng SerializeWithLengthPrefix. Dưới đây là những gì tôi có bây giờ:
[Serializable,
ProtoContract,
ProtoInclude(50, typeof(BeginRequest))]
abstract internal class BaseMessage
{
abstract public UInt16 messageType { get; }
}
[Serializable,
ProtoContract]
internal class BeginRequest : BaseMessage
{
public override UInt16 messageType
{
get { return 1; }
}
}
Tiếp nhận một đối tượng:
//where "this.Ssl" is an SslStream.
BaseMessage message =
ProtoBuf.Serializer.DeserializeWithLengthPrefix<BaseMessage>(
this.Ssl, ProtoBuf.PrefixStyle.Base128);
Để gửi một đối tượng:
//where "this.Ssl" is an SslStream and "message" can be anything that
// inherits from BaseMessage.
ProtoBuf.Serializer.SerializeWithLengthPrefix<BaseMessage>(
this.Ssl, message, ProtoBuf.PrefixStyle.Base128);
tôi quên đề cập đến, tôi serializing trong .NET 3.5 trên Windows và deserializing trong Mono 2.2 và đang sử dụng dlls protobuf-net thích hợp trên mỗi nền tảng. –
Tôi sẽ quay lại để đọc và đăng câu trả lời trong khoảng nửa giờ ... phải chạy vào lúc này, xin lỗi. BTW - bản phát hành tiếp theo có các trình bao bọc không chung chung được tích hợp sẵn - vẫn còn trên máy tính xách tay của tôi vào lúc này. –
btw - Tôi đang làm việc để hợp nhất bản sao cục bộ của mình, vì vậy tôi có thể cam kết các thay đổi để làm cho việc này trở nên dễ dàng hơn. Tôi có một kiểm tra lỗi xuất sắc, nhưng điều đó bao gồm mã mới, vì vậy tôi nội dung cam kết nó (được đánh dấu là bỏ qua) nếu nó giúp. –