I'm trying to send a class with some variables trough named pipes, and it keeps giving me this error when I try to deserialize the data I received.
This is the serialization/deserialization code:
// Serialize into bytes
private byte[] SerializeToBytes<T>(T source)
{
using (var stream = new MemoryStream())
{
var formatter = new BinaryFormatter();
formatter.Serialize(stream, source);
return stream.ToArray();
}
}
// Deserialize from bytes (BinaryFormatter)
private T DeserializeFromBytes<T>(byte[] source)
{
using (var stream = new MemoryStream(source))
{
var formatter = new BinaryFormatter();
stream.Seek(0, SeekOrigin.Begin);
return (T)formatter.Deserialize(stream);
}
}
Both projects use this same code, I have a server project and a client project that can send and receive data, it was working fine with sending and receiving strings but in the end i need it to send and receive custom data like a class.
this is how I send / recieve data:
// Sending Data
private void _SendBttn_Click(object sender, EventArgs e)
{
AchievementInfo info = new AchievementInfo("1337", true);
server.WriteBytes(SerializeToBytes(info));
}
// Receiving Data
private void _ServerWorker_DoWork(object sender, DoWorkEventArgs e)
{
server = new ServerPipe("testerSV", p => p.StartByteReaderAsync());
server.DataReceived = (sndr, args) => this.BeginInvoke((Action)(() =>
_RecievedData.Text =
DeserializeFromBytes<AchievementInfo>(args.Data).ToString()));
}
Both projects also have the class AchievementInfo this is what it looks like:
[Serializable]
public class AchievementInfo
{
public string ID { get; }
public bool UnlockState { get; set; }
public bool CurrentUnlockState { get; }
public AchievementInfo() {}
public AchievementInfo(string id, bool currentState)
{
ID = id;
CurrentUnlockState = currentState;
UnlockState = currentState;
}
}
I've search for other posts with a similar problem but none of the solutions worked so far. I currently have no idea what's causing this, but I know it's something to do with it being 2 different projects, since serializing and deserializing in the same project works just fine.
Edit: Projects are named NamedPipes and PipesClient
CodePudding user response:
The problem is your use of two separate AchievementInfo
classes, one in each project. What's happening is that the full namespace (or something calculated from it) of the class is encoded into the serialised data. When it is deserialised via a separate project it can't find the class because it's looking for the one in the namespace of the project that serialised it.
The correct way to do this is to define a DTO class in a shared library, and serialise and deserialise that. Often the DTO class would be a totally separate class than the classes at either end, and you'd convert the DTO appropriately at each end before/after serialising.
However for your case, you could try the quick and dirty solution of just using the AchievementInfo
class for the DTO. Just make sure it's in a shared class library so the namespace is the same at both ends.
Do note that BinaryFormatter
is considered insecure, and Microsoft warn against using it.