2

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'.

Ziggler
  • 3,361
  • 3
  • 43
  • 61
  • 2
    question: are you *restricted* to `BinaryFormatter`; there are other serializers that might be able to work here, but that isn't worth discussing if you really mean "with `BinaryFormatter`"; if you mean "with `BinaryFormatter`", the only option I can think of is "surrogates" – Marc Gravell Aug 03 '20 at 19:06
  • @MarcGravell... SerializeToByteArray is my method and I can use any formatter unless I get it reviewed by security team and it works.What you mean by surrogates? – Ziggler Aug 03 '20 at 19:08
  • 1
    here's a walkthrough of surrogates - it is for pretty much exactly this scenario: https://riptutorial.com/csharp/example/14386/serialization-surrogates--implementing-iserializationsurrogate- - and as for other serializers: I'm biased, so I was thinking of protobuf-net :) – Marc Gravell Aug 03 '20 at 19:11
  • 1
    Can you serialise to json and then serialize to byte[] ? – Neil Aug 03 '20 at 19:12
  • @MarcGravell.. I will look into it... – Ziggler Aug 03 '20 at 19:15
  • @Neil... as I am typing this I am trying it. My first try was to convert directly... – Ziggler Aug 03 '20 at 19:15

1 Answers1

2

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

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900