Search code examples
c#model-view-controllerserializationdeserializationbin

Serializing object then deserialize as list<object> C#


I'm stuck in this problem and I've been searching anywhere for answers but didn't found something that fits my problem. I want to serialize object and save it into a binary file, and deserialize it as list since it will returning multiple rows of records.

So, this is my class

[Serializable]
public class DTOMultiConfig
{
    public string Key { get; set; }
    public string KeyValue { get; set; }
}

[Serializable]
public class DTOMultiConfigs : List<DTOMultiConfig>
{
    public void Dispose()
    {
    }
}

and I'm using these methods I found online. This is how I serialize my object, this part works

public void Editor_Config(DTOMultiConfig dto)
{
    if (dto.ID == 0)//new
    {
        dto.ID = 0;
        WriteToBinaryFile(BinPath, dto, true);
    }
    else//edit
    {
    }
}

public static void WriteToBinaryFile<T>(string filePath, T objectToWrite, bool append = false)
{
    using (Stream stream = System.IO.File.Open(filePath, append ? FileMode.Append : FileMode.Create))
    {
        var binaryFormatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
        binaryFormatter.Serialize(stream, objectToWrite);
    }
}

This is how I use the deserialize method, I'm not sure , I'm sure I'm doing it the wrong way because it's not working at all. The ReadFromBinaryFile stops working right before the 'return' statement.

public PartialViewResult ShowListOfConfigs()
{
    List<DTOMultiConfig> dto = new List<DTOMultiConfig>();

    //DESERIALIZE  

    dto = ReadFromBinaryFile<List<DTOMultiConfig>>(BinPath);
    return PartialView("_ListOfConfigs", dto);
}

public static T ReadFromBinaryFile<T>(string filePath)
{
    using (Stream stream = System.IO.File.Open(filePath, FileMode.Open))
    {
        var binaryFormatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
        return (T)binaryFormatter.Deserialize(stream);
    }
}

Any answers with some explanation will be appreciated.


Solution

  • Let me try to explain. Imagine you weren't using a binary serializer but instead an XML Serializer. In this case what you'd be writing would look kind of like this:

    <DTOMultiConfig>
      <Key>SomeKey</Key>
      <Value>SomeValue</Value>
    </DTOMultiConfig>
    

    Now, when you read your data back, you are attempting to deserialize your single instance into a List which, however, would need to look somewhat similar to this:

    <ListOfDTOMultiConfigs>
      <DTOMultiConfig>
        <Key>SomeKey</Key>
        <Value>SomeValue</Value>
      </DTOMultiConfig>
      [...potentially more elements here...]
    </ListOfDTOMultiConfigs>
    

    That simply cannot work. In a binary world, the actual data in the file would look different. However, the same problem persists: You cannot write one type and read a different one back unless their structure is absolutely identical.

    In order to deal with you concrete case you could read back a single element and then put it in a list if you need the list. Or your could write a list with a single element to your file and then read that list back using your above code.

    EDIT:

    In your comment above you say that you'd expect that writing a single element twice to the file should give you a list. Going back to my example above, writing a single element twice would give you this:

    <DTOMultiConfig>
      <Key>SomeKey</Key>
      <Value>SomeValue</Value>
    </DTOMultiConfig>
    <DTOMultiConfig>
      <Key>SomeKey</Key>
      <Value>SomeValue</Value>
    </DTOMultiConfig>
    

    If you compare this to my example for the representation of a list above you will see that they are not identical and hence cannot be used interchangeably.