I am converting a program from VB.NET to C# (And learning C# in the process). I want to convert old binary serialized files into XML or JSON data for the new system, however, when converting in the new C# program, the object is populated to null values. The deserialization works fine in VB.NET. (The type objects are identical)
EDIT: I know BinarySerializer is not the way to go, this is written to read OLD serialized files using the BinarySerializer and convert them to xml.
Working VB Solution:
Type Definition:
<XmlType("GameNfo")>
<Serializable()>
Public Class OldGameNfo
' Public Property ImgList As New Collection(Of ImgNfo)
Public Property Round As New Collection(Of OldRoundNfo)
Public Property Name As String = ""
Public Property FileName As String = ""
<XmlIgnore()> Public Property AnswerRound As Integer = 0
<XmlIgnore()> Public Property AnswerQuestion As Integer = 0
<XmlIgnore()> Public Property CurrentRound As Integer = -1
<XmlIgnore()> Public Property CurrentQuestion As Integer = -1
<XmlIgnore()> Public Property Completed As Boolean = False
Public Property Description As String = ""
<XmlIgnore()> Public Property SelectedRound As Integer = -1
<XmlIgnore()> Public Property SelectedQuestion As Integer = -1
Public Property Bonus As New OldBonusNfo
Public Property Created As New Date(1000, 1, 1)
End Class
<XmlType("BonusNfo")>
<Serializable()> Public Class OldBonusNfo
Public Property BonusImage As String = ""
Public Property Question As String = ""
Public Property Answer As String = ""
Public Property PointValue As Integer = 0
Public Property Mosaic As Integer = 0
Public Property Enabled As Boolean = False
Public Property WheelPhrase As String = ""
Public Property WheelCategory As String = ""
Public Property WheelLetters As String = ""
Public Property ClueCollection As New Collection(Of String)
Public Property BonusType As BNType = BNType.None
End Class
<XmlType("RoundNfo")>
<Serializable()> Public Class OldRoundNfo
Public Property BonusPlacement As Integer = 0
Public Property Name As String = ""
Public Property Type As String = ""
Public Property Category As String = ""
Public Property Number As Integer = 0
Public Property Description As String = ""
Public Property IntroMedia As String = "[DEFAULT]"
Public Property QuestionIntroMedia As String = "[DEFAULT]"
Public Property AnswerIntroMedia As String = "[DEFAULT]"
Public Property QuestionBackMedia As String = "[DEFAULT]"
Public Property AnswerBackMedia As String = "[DEFAULT]"
<XmlIgnore()> Public Property Completed As Boolean = False
Public Property Freeze As Boolean = True
Public Property Gamble As Boolean = True
Public Property Lucky As Boolean = True
Public Property DefaultPointValue As Integer
Public Property Question As New Collection(Of OldQuestionNfo)
Public Property Bonus As New OldBonusNfo
End Class
<XmlType("QuestionNfo")>
<Serializable()> Public Class OldQuestionNfo
Public Property RoundStarted As Boolean = False
Public Property Created As New Date(1000, 1, 1)
<XmlIgnore()> Public Property Frozen As Boolean = False
Public Property Category As String = ""
Public Property Number As Integer = 0
Public Property PointValue As Integer = 0
Public Property Type As String = ""
Public Property Question As String = ""
Public Property QuestionAudio As String = ""
Public Property QuestionImage As String = ""
Public Property QuestionVideo As String = ""
Public Property QuestionExtra As String = ""
Public Property Freeze As Boolean = True
Public Property Gamble As Boolean = True
Public Property Lucky As Boolean = True
Public Property HasBonus As Boolean = False
Public Property ShowOrder As OrderType = OrderType.QuestionMedia
Public Property AnswerList As New Collection(Of OldAnswerNfo)
Public Property Answer As New OldAnswerNfo
Public Property AnswerAudio As String = ""
Public Property AnswerImage As String = ""
Public Property AnswerVideo As String = ""
Public Property AnswerExtra As String = ""
<XmlIgnore()> Public Property Asked As Boolean = False
<XmlIgnore()> Public Property Answered As Boolean = False
<XmlIgnore()> Public Property Completed As Boolean = False
Public Property QuestionIntroMedia As String = "[DEFAULT]"
Public Property AnswerBackMedia As String = "[DEFAULT]"
Public Property QuestionBackMedia As String = "[DEFAULT]"
Public Property AnswerIntroMedia As String = "[DEFAULT]"
Public Property Choices As New Collection(Of String)
Public Property ID As String = ""
<XmlIgnore()> Public Property QuestionShown As Boolean = False
<XmlIgnore()> Public Property AnswerShown As Boolean = False
<XmlIgnore()> Public Property VideoShown As Boolean = False
<XmlIgnore()> Public Property AudioShown As Boolean = False
End Class
<XmlType("AnswerNfo")>
<Serializable()> Public Class OldAnswerNfo
Public Property Answer As String = ""
Public Property PointValue As Integer = 0
End Class
Code:
Public Sub ConvertOldGame(ByVal gameDirectory As String)
Dim GameLoad As OldGameNfo
Using fs As New FileStream(System.IO.Path.Combine(gameDirectory, "gData.fb"), FileMode.Open)
Dim formatter As New BinaryFormatter
formatter.Binder = New Version1ToVersion2DeserializationBinder
GameLoad = DirectCast(formatter.Deserialize(fs), OldGameNfo)
End Using
End Sub
NotInheritable Class Version1ToVersion2DeserializationBinder
Inherits SerializationBinder
Public Overrides Function BindToType(ByVal assemblyName As String, ByVal typeName As String) As System.Type
Dim typeToDeserialize As System.Type
typeName = typeName.Replace("GameNfo", "OldGameNfo")
typeName = typeName.Replace("RoundNfo", "OldRoundNfo")
typeName = typeName.Replace("BonusNfo", "OldBonusNfo")
typeName = typeName.Replace("QuestionNfo", "OldQuestionNfo")
typeName = typeName.Replace("AnswerNfo", "OldAnswerNfo")
typeToDeserialize = GetType(String.Format("{0}, {1}", typeName, assemblyName))
Return typeToDeserialize
End Function
End Class
Non-working C# version:
Type Definition:
using System;
using System.Collections.Generic;
namespace TriviaBomb.Old
{
[XmlType("GameNfo")]
[Serializable()]
public class GameNfo
{
// Public Property ImgList As New Collection(Of ImgNfo)
public Collection<RoundNfo> Round { get; set; } = new Collection<RoundNfo>();
public string Name { get; set; } = "";
public string FileName { get; set; } = "";
[XmlIgnore()]
public int AnswerRound { get; set; } = 0;
[XmlIgnore()]
public int AnswerQuestion { get; set; } = 0;
[XmlIgnore()]
public int CurrentRound { get; set; } = -1;
[XmlIgnore()]
public int CurrentQuestion { get; set; } = -1;
[XmlIgnore()]
public bool Completed { get; set; } = false;
public string Description { get; set; } = "";
[XmlIgnore()]
public int SelectedRound { get; set; } = -1;
[XmlIgnore()]
public int SelectedQuestion { get; set; } = -1;
public BonusNfo Bonus { get; set; } = new BonusNfo();
public DateTime Created { get; set; } = new DateTime(1000, 1, 1);
}
[XmlType("BonusNfo")]
[Serializable()]
public class BonusNfo
{
public string BonusImage { get; set; } = "";
public string Question { get; set; } = "";
public string Answer { get; set; } = "";
public int PointValue { get; set; } = 0;
public int Mosaic { get; set; } = 0;
public bool Enabled { get; set; } = false;
public string WheelPhrase { get; set; } = "";
public string WheelCategory { get; set; } = "";
public string WheelLetters { get; set; } = "";
public Collection<string> ClueCollection { get; set; } = new Collection<string>();
public BNType BonusType { get; set; } = BNType.None;
}
[XmlType("RoundNfo")]
[Serializable()]
public class RoundNfo
{
public int BonusPlacement { get; set; } = 0;
public string Name { get; set; } = "";
public string Type { get; set; } = "";
public string Category { get; set; } = "";
public int Number { get; set; } = 0;
public string Description { get; set; } = "";
public string IntroMedia { get; set; } = "[DEFAULT]";
public string QuestionIntroMedia { get; set; } = "[DEFAULT]";
public string AnswerIntroMedia { get; set; } = "[DEFAULT]";
public string QuestionBackMedia { get; set; } = "[DEFAULT]";
public string AnswerBackMedia { get; set; } = "[DEFAULT]";
[XmlIgnore()]
public bool Completed { get; set; } = false;
public bool Freeze { get; set; } = true;
public bool Gamble { get; set; } = true;
public bool Lucky { get; set; } = true;
public int DefaultPointValue { get; set; }
public Collection<QuestionNfo> Question { get; set; } = new Collection<QuestionNfo>();
public BonusNfo Bonus { get; set; } = new BonusNfo();
}
[XmlType("QuestionNfo")]
[Serializable()]
public class QuestionNfo
{
public bool RoundStarted { get; set; } = false;
public DateTime Created { get; set; } = new DateTime(1000, 1, 1);
[XmlIgnore()]
public bool Frozen { get; set; } = false;
public string Category { get; set; } = "";
public int Number { get; set; } = 0;
public int PointValue { get; set; } = 0;
public string Type { get; set; } = "";
public string Question { get; set; } = "";
public string QuestionAudio { get; set; } = "";
public string QuestionImage { get; set; } = "";
public string QuestionVideo { get; set; } = "";
public string QuestionExtra { get; set; } = "";
public bool Freeze { get; set; } = true;
public bool Gamble { get; set; } = true;
public bool Lucky { get; set; } = true;
public bool HasBonus { get; set; } = false;
public OrderType ShowOrder { get; set; } = OrderType.QuestionMedia;
public Collection<AnswerNfo> AnswerList { get; set; } = new Collection<AnswerNfo>();
public AnswerNfo Answer { get; set; } = new AnswerNfo();
public string AnswerAudio { get; set; } = "";
public string AnswerImage { get; set; } = "";
public string AnswerVideo { get; set; } = "";
public string AnswerExtra { get; set; } = "";
[XmlIgnore()]
public bool Asked { get; set; } = false;
[XmlIgnore()]
public bool Answered { get; set; } = false;
[XmlIgnore()]
public bool Completed { get; set; } = false;
public string QuestionIntroMedia { get; set; } = "[DEFAULT]";
public string AnswerBackMedia { get; set; } = "[DEFAULT]";
public string QuestionBackMedia { get; set; } = "[DEFAULT]";
public string AnswerIntroMedia { get; set; } = "[DEFAULT]";
public Collection<string> Choices { get; set; } = new Collection<string>();
public string ID { get; set; } = "";
[XmlIgnore()]
public bool QuestionShown { get; set; } = false;
[XmlIgnore()]
public bool AnswerShown { get; set; } = false;
[XmlIgnore()]
public bool VideoShown { get; set; } = false;
[XmlIgnore()]
public bool AudioShown { get; set; } = false;
}
[XmlType("AnswerNfo")]
[Serializable()]
public class AnswerNfo
{
public string Answer { get; set; } = "";
public int PointValue { get; set; } = 0;
}
}
Code:
static bool ConvertGame(string sourcePath)
{
Old.GameNfo loadGame;
using System.IO.FileStream fs = new(System.IO.Path.Combine(sourcePath, "gData.fb"), FileMode.Open);
BinaryFormatter formatter = new();
formatter.Binder = new Version1ToVersion2DeserializationBinder();
#pragma warning disable SYSLIB0011 // << Surpress depreciation warning
loadGame = (Old.GameNfo)formatter.Deserialize(fs);
return returnValue;
}
private sealed class Version1ToVersion2DeserializationBinder : SerializationBinder
{
public override System.Type BindToType(string assemblyName, string typeName)
{
//System.Type typeToDeserialize = null;
typeName = typeName.Replace("GameNfo", "Old.GameNfo");
typeName = typeName.Replace("RoundNfo", "Old.RoundNfo");
typeName = typeName.Replace("BonusNfo", "Old.BonusNfo");
typeName = typeName.Replace("QuestionNfo", "Old.QuestionNfo");
typeName = typeName.Replace("AnswerNfo", "Old.AnswerNfo");
assemblyName = Assembly.GetExecutingAssembly().FullName;
Type typeToDeserialize = Type.GetType(String.Format("{0}, {1}", typeName, assemblyName));
return typeToDeserialize;
}
}
To note, this yields the same result whether altering the assemblyName or not in the C# code. Both are TriviaBomb, one is version 0.97, other is 2.0
The namespaces had no effect, same result with keeping in the same namespace (Not .Old as shown in the C# version, kept the OLD version in it's own namespace to preserve object names)
I can't seem to find a solution for days now and I'm hoping it's due to my inexperience in C#.
EDIT: I can verify it is finding the right properties/fields by breaking on the Version1ToVersion2DeserializationBinder class, but no data is being imported. If I change a field name to one that is not in the Object, the operation fails.