Here is what I tried but I get this error:
Error CS0029 Cannot implicitly convert type 'ListBoxAndDictionary.CountriesAndCities' to 'System.Collections.Generic.Dictionary<string, System.Collections.Generic.List>'
Here is my code:
private Dictionary<string, List<string>> dictCountryAndCities = new
Dictionary<string, List<string>>();
private void button12_Click(object sender, EventArgs e)
{
SaveFileDialog sfd = new SaveFileDialog();
sfd.FileName = "CountriesAndCities";
sfd.DefaultExt = ".xml";
sfd.Filter = "XML (*.xml)|*.xml|All Files (*.*)|*.*";
var sfdResult = sfd.ShowDialog();
if (sfdResult == DialogResult.Cancel)
return;
var container = new CountriesAndCities
{
DictCountriesAndCities = dictCountryAndCities
};
using (var writer = XmlWriter.Create(sfd.FileName))
(new XmlSerializer(typeof(CountriesAndCities))).Serialize(writer, container);
}
private void button11_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.DefaultExt = ".xml";
ofd.Filter = "XML (*.xml)|*.xml|All Files (*.*)|*.*";
var ofdResult = ofd.ShowDialog();
if (ofdResult == DialogResult.Cancel)
return;
dictCountryAndCities = new Dictionary<string, List<string>>();
XmlSerializer serializer = new XmlSerializer(typeof(CountriesAndCities));
using (var reader = new StreamReader(ofd.FileName))
{
dictCountryAndCities = serializer.Deserialize(reader) as CountriesAndCities;
//Error CS0029 Cannot implicitly convert type 'ListBoxAndDictionary.CountriesAndCities' to 'System.Collections.Generic.Dictionary<string, System.Collections.Generic.List<string>>'
}
//binding DataSource for listBox1
listBox1.DataSource = dictCountryAndCities.Keys.ToList();
}
[Serializable]
[XmlRoot("CountriesAndCities")]
public class CountriesAndCities
{
public List<Country> Name
{
get { return DictCountriesAndCities.Select(x => new Country { CountryName = x.Key, Cities = x.Value }).ToList(); }
set { DictCountriesAndCities = value.ToDictionary(x => x.CountryName, x => x.Cities); }
}
[XmlIgnore]
public Dictionary<string, List<string>> DictCountriesAndCities { get; set; }
}
[Serializable]
public class Country
{
public string CountryName { get; set; }
public List<string> Cities { get; set; }
}
You have a few problems with your XML serialization code.
Firstly, you need to modify your CountriesAndCities
DTO as follows, replacing the List<Country> Name
surrogate property with a Country [] Name
property instead:
[XmlRoot("CountriesAndCities")]
public class CountriesAndCities
{
public Country [] Name // Replace the List<Country> with Country []
{
get { return DictCountriesAndCities.Select(x => new Country { CountryName = x.Key, Cities = x.Value }).ToArray(); }
set { DictCountriesAndCities = value?.ToDictionary(x => x.CountryName, x => x.Cities); }
}
[XmlIgnore]
public Dictionary<string, List<string>> DictCountriesAndCities { get; set; }
}
public class Country
{
public string CountryName { get; set; }
public List<string> Cities { get; set; }
}
Secondly, modify your serialization code as follows:
var container = new CountriesAndCities
{
DictCountriesAndCities = dictCountriesAndCities,
};
using (var writer = XmlWriter.Create(sfd.FileName, new XmlWriterSettings { Indent = true })) // Indentation is for visualization purposes only
(new XmlSerializer(typeof(CountriesAndCities))).Serialize(writer, container);
Finally, change your deserialization code as follows:
using (var reader = new StreamReader(ofd.FileName))
{
dictCountriesAndCities = ((new XmlSerializer(typeof(CountriesAndCities))).Deserialize(reader) as CountriesAndCities)
?.DictCountriesAndCities;
}
Notes:
Your "Error CS0029" is caused because you attempt to assign a value of type CountriesAndCities
to a Dictionary<string, List<string>>
. Instead, you must access the property DictCountriesAndCities
.
In your method button11_Click()
you are deserializing your XML into a local variable dictCountryAndCities
, then binding to its keys:
dictCountryAndCities = new Dictionary<string, List<string>>();
XmlSerializer serializer = new XmlSerializer(typeof(CountriesAndCities));
using (var reader = new StreamReader(ofd.FileName))
{
dictCountryAndCities = serializer.Deserialize(reader) as CountriesAndCities;
//Error CS0029 Cannot implicitly convert type 'ListBoxAndDictionary.CountriesAndCities' to 'System.Collections.Generic.Dictionary<string, System.Collections.Generic.List<string>>'
}
You are not updating the class member dictCountryAndCities
at all. This seems wrong. However, it's not clear from your question what you want to be doing there, so I can't really recommend a fix.
The [Serializable]
attribute is not required or used by XmlSerializer
, and can be removed.
For an explanation as to why you should use Country []
instead of List<Country>
for your surrogate Name
property, see this answer to Cannot deserialize XML into a list using XML Deserializer.
Demo fiddle here.