Nick R. Nick R. - 21 days ago 4
C# Question

C# Serialization - List<object> that contain a string and List<objects>

I have a large amount of data I have to serialize to XML files. I have no problem getting all my other classes to serialize to their own files, except for this one class. Specifically, the

List<lCLSIDs> _CLSIDs
sub-class that I have commented out below. The rest of this class serializes fine.

This is the class I'm trying to serialize.

[Serializable]
public class serCOMInfo
{
public List<oCOMFiles> ListOfCOMFiles { get; set; }
public SerializableDictionary<string, oTypeLib> _TypeLib { get; set; }
//public List<lCLSIDs> _CLSIDs { get; set; }
public List<string> COMErrors { get; set; }
}


AND, here are the sub-classes of the above:

[Serializable]
public class oCOMFiles
{
public string Name { get; set; }
public string Path { get; set; }
public oCOMFiles() { }
public oCOMFiles(string sName, string sPath)
{
this.Name = sName;
this.Path = sPath;
}
}

[Serializable]
public class oTypeLib
{
public string Name { get; set; }
public string GUID { get; set; }
public string Version { get; set; }
public string Description { get; set; }
public string FileSize { get; set; }
public string HelpString { get; set; }
public int LCID { get; set; }
public string ContainingFile { get; set; }
public oTypeLib() { }
public oTypeLib(string sName, string sGUID, string sVersion, string sDescription, string sFileSize, string sHelpString, int sLCID, string sContainingFile)
{
this.Name = sName;
this.GUID = sGUID;
this.Version = sVersion;
this.Description = sDescription;
this.FileSize = sFileSize;
this.HelpString = sHelpString;
this.LCID = sLCID;
this.ContainingFile = sContainingFile;
}
}

[Serializable]
public class lCLSIDs
{
public string COMFileName;
public List<oCLSIDs> oItems;
public lCLSIDs() { }
public lCLSIDs(string _COMFileName, List<oCLSIDs> _oItems)
{
this.COMFileName = _COMFileName;
this.oItems = _oItems;
}
}

[Serializable]
public class oCLSIDs
{
public string ProgID { get; set; }
public string GUID { get; set; }
public string Version { get; set; }
public Array AttributeArray { get; set; }
public short AttributeStrings { get; set; }
public oCLSIDs() { }
public oCLSIDs(string sProgID, string sGUID, string sVersion, Array arrAttributeArray, short stAttributeStrings)
{
this.ProgID = sProgID;
this.GUID = sGUID;
this.Version = sVersion;
this.AttributeArray = arrAttributeArray;
this.AttributeStrings = stAttributeStrings;
}
}


The following code snippet is what I use for all classes. It works for all of them, even the one above when I comment out the
public List<lCLSIDs> _CLSIDs { get; set; }
line.

Serialize_Classes.serCOMInfo oCOMInfo = frmCOMInfo.Instance.COMInfo_SaveForm();
File_Output.CreateXMLFile(oCOMInfo, PRCxGlobals.sCOMInfoFile);


And, finally, here is my CreateXMLFile code:

private static Stream fstream;
public static bool CreateXMLFile(object oFormData, string sFileName)
{
string sSaveFile = Path.Combine(sZipDirForXMLs, sFileName);
SaveFileDialog sfdl = new SaveFileDialog();
sfdl.FileName = sSaveFile;
try
{
fstream = sfdl.OpenFile();
XmlSerializer ser = new XmlSerializer(oFormData.GetType());
using (StreamWriter wr = new StreamWriter(fstream))
{
ser.Serialize(wr, oFormData);
}
fstream.Close();
return true;
}
catch (Exception ex)
{
fstream.Close();
Logger.Global.Error("Unable to open file: " + ex.Message);
return false;
}
}


Here is the error I get when I run my program:
ERROR: "There was an error reflecting type 'PCRx.Net.Modules.Serialize_Classes.serCOMInfo'."

This error made me think the type wasn't coming over well enough, so I have tried changing the XmlSerializer line for just this one set of data:
XmlSerializer ser = new XmlSerializer(typeof(Serialize_Classes.serCOMInfo));

That didn't work.

I've worked on this for a few days now and originally, this class was a dictionary. I switched it to a list of objects containing a list of objects because I thought the problem was with the SeralizableDictionary. I was wrong. I have no problem serializing a list of objects that doesn't contain a list or more objects. Only this particular set of data where it's a list of objects that contain another list of objects. I now think it has something to do with having another List of Objects inside of a List of Objects. Not sure, but that's my thought.

These are the only two questions I found that were similar to this one:
1) C# Serialize an object with a list of objects in it
2) XML Serialize generic list of serializable objects

Both of these use tags which doesn't seem to be needed for mine. All my other XMLs are exactly the way I want them. Do you think this is something I should try?

I was hoping to avoid making more major changes because there is a lot of code involved in collecting this data. I'm out of options though so I'm curious of what other think I should do here.

I should also mention that I have to deserialize the XML file and load it back into the application. So far, I have the deserializing working for all my other data, but I haven't gotten to that for this set since I can't get the data to serialize.

Thank you for reading this. Let me know if you need any more information.

Answer

The problem lies here:

public Array AttributeArray { get; set; }

The Serializer doesn't know how to serialize and unserialize the generic Array type. Your exception has an inner exception which says

InvalidOperationException: You must implement a default accessor on System.Array because it inherits from ICollection

The generic Array class is not meant to be used directly in C#. Use a typed array instead, for example

public string[] AttributeArray { get; set; }