Ziggler
Ziggler

Reputation: 3500

C# Serialize class into byte[] that is not marked as Serializable

I have classes like below and which I cannot change since these are almost 20+ years old classes and they are already in production used by many applications. This is maintained by a team and before I go to them and ask to make change which I feel will be big change I need to make sure that I explore all the options.

[Serializable]
public class MyDTO
{
  public string FullName {get;set;}
  public List<Address> Addresses {get;set}
}

// Note: It is not marked as Serializable
public class Address
{
  public string FullAddress {get;set;}
  
}

I am creating MyDTO like below

List<Address> myAddresses = new List<Address>()
{
   new Address() { FullAddress =" FullAddress1"},
   new Address() { FullAddress =" FullAddress2"}
}

MyDTO dto = new MyDTO() 
{
  FullName = "FullName",
  Addresses = myAddresses
}

Now I am trying to convert dto in byte[] like below.

public byte[] SerializeToByteArray(MyDTO dto)
{
  byte[] byteArray = null;
  BinaryFormatter bf = new BinaryFormatter();
  using (MemoryStream ms = new MemoryStream())
  {
    bf.Serialize(ms, dto);
    byteArray = ms.ToArray();
  }
  return byteArray;
}

I am getting exception as Type 'xxx.Address' in Assembly 'xxx.yyy.zzz, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' is not marked as serializable.

Can anybody please tell me how we can solve this issue without making Address as Serializable. I need to convert dto into byte[]

Thanks in advance.

UPDATE 1

I tried what @Neil suggested in comments and now my initial problem is solved ( I assume ) but I get new problem so I feel what I am doing is wrong.

This is what I am doing now

public byte[] SerializeToByteArray<T>(T dto)
{
 byte[] byteArray = null;
 BinaryFormatter bf = new BinaryFormatter();
 using (MemoryStream ms = new MemoryStream())
 {
   bf.Serialize(ms, dto);
   byteArray = ms.ToArray()
 }
 return byteArray;
}
string jsonString = Newtonsoft.Json.JsonConvert.SerializeObject(dto);
byte[] byteArray = SerializeToByteArray(jsonString);
string dtoByteArrayBase64String = Convert.ToBase64String(byteArray);

I send dtoByteArrayBase64String to server side and I am receiving it. On server I try to re-create MyDTO object like below

byte[] inputDTOByteArray = Convert.FromBase64String(dtoByteArrayBase64String);
MyDTO  myDTO = DeserializeFromByteArray<MyDTO>(inputDTOByteArray);

public T DeserializeFromByteArray<T>(byte[] byteArray)
{
  T dto;
  BinaryFormatter bf = new BinaryFormatter();
  using (MemoryStream ms = new MemoryStream(byteArray))
  {
    object obj = bf.Deserialize(ms);
    dto = (T)obj; // getting error here
  }
  return dto;
}

I am getting below error Unable to cast object of type 'System.String' to type 'MyDTO'.

Upvotes: 2

Views: 1106

Answers (1)

Marc Gravell
Marc Gravell

Reputation: 1064204

If you are tied to BinaryFormatter, the feature you're looking for is "surrogates"; this isn't a small topic, so it is hard to give a concise example, but a full walkthrough is covered here; essentially, a surrogate is a custom type that gets used internally instead of the type it encounters, so your custom type can do all the extra logic required.

However! In general, BinaryFormatter should be considered legacy and obsolete. Nobody is taking it away from you, and it is going to keep working (on .NET Framework, at least), but: if possible, you should consider looking at alternative options. For some of the reasons: see here

Upvotes: 2

Related Questions