3

I have a C# program that retrieves data from a webpage and then organizes the content into a dictionary. So far the program get the data from the web every time I run it cause there is no alternative data source. The problem is that if I am offline I can't retrieve the data so I don't have data to work with. Can I save the entire dictionary locally so that I can then load it and run my analysis even if I am offline?

The dictionary to save is myData:

Dictionary<string, itemdata> myData = new Dictionary<string, itemdata>();

where the key is a string and represent the name of an item and itemdata in turn is defined as:

public class itemdata
{
    // Fields
    public double itemWeight;
    public double itemSize;
    public double itemPrice;

    // class constructor
    public itemdata(double myItemWeight, double myItemSize, double myItemPrice)
    {
        itemWeight= myItemWeight;
        itemSize= myItemSize;
        itemPrice= myItemPrice;
    }

    // Public properties (read only access to these fields)
    public double myItemWeight
    {
        get { return itemWeight; }
    }

    public double myItemSize
    {
        get { return itemSize; }
    }

    public double myItemPrice
    {
        get { return itemPrice; }
    }
}

So in my main class I retrieve some data for some items and then I populate:

itemdata myItemMap = new itemdata (itemWeight, itemSize, itemPrice)

and insert everything into the dictionary:

myData.Add(itemName, myItemMap);

Once all data have been retrieved and organized into the myData dictionary, I would like this to be saved locally.

Thanks for all the suggestions you gave me so far. Saving to XML seems to be a good choice but I would appreciate some clear example how to deal with my particular dictionary since it is not simply "one key and one value" but a slightly more complex "one key with multiple values/fields".

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
mickG
  • 335
  • 5
  • 13
  • 1
    You may find this question interesting: [Serialize an object (w/ Dictionary) to JSON](http://stackoverflow.com/questions/22105722/serialize-an-object-w-dictionary-to-json) – t3chb0t Dec 12 '14 at 10:03
  • Thank you. Can you show me the line code to use to save the dictionary? – mickG Dec 12 '14 at 10:24
  • [How to: Write to a Text File (C# Programming Guide)](http://msdn.microsoft.com/en-us/library/8bh11f1k.aspx) ... you should consider reading some C# tutorials. – t3chb0t Dec 12 '14 at 10:27

2 Answers2

1

Another thing you could do is serialize it to XML using the built in serializer. The type you will be serializing has to implement ISerializable. That is the only requirement. The good thing is that .NET is going to take care of everything else for you.

Phoenix
  • 913
  • 1
  • 8
  • 18
1

Generally you need to a list of some custom class objects to be able to use XmlSerializer for saving into XML. Dictionary is not directly serializable into XML. Here I provide example use:

class Program
{
  static void Main(string[] args)
  {
    var myData = new Dictionary<string, ExampleDataClass>()
    {
      { "First", new ExampleDataClass() { Name = "John", Surname = "Doe" } },
      { "Second", new ExampleDataClass() { Name = "Foo", Surname = "Bar" } }
    };
    var fileName = @"C:\MyPath\dict.xml";
    myData.SaveToXml(fileName);
    myData.Clear();
    myData = MySerializer.LoadFromXml<string, ExampleDataClass>(fileName);
  }
}

public class ExampleDataClass
{
  public string Name { get; set; }
  public string Surname { get; set; }
}

public class KeyValue<TKey, TValue>
{
  public TKey Key { get; set; }
  public TValue Value { get; set; }
}

static class MySerializer
{
  public static void SaveToXml<TKey, TValue>(this Dictionary<TKey, TValue> dictionary, string fileName)
  {
    var serializer = new XmlSerializer(typeof(List<KeyValue<TKey, TValue>>));

    using (var s = new StreamWriter(fileName))
    {
      serializer.Serialize(s, dictionary.Select(x => new KeyValue<TKey, TValue>() { Key = x.Key, Value = x.Value }).ToList());
    }
  }

  public static Dictionary<TKey, TValue> LoadFromXml<TKey, TValue>(string fileName)
  {
    var serializer = new XmlSerializer(typeof(List<KeyValue<TKey, TValue>>));

    using (var s = new StreamReader(fileName))
    {
      var list = serializer.Deserialize(s) as List<KeyValue<TKey, TValue>>;
      return list.ToDictionary(x => x.Key, x => x.Value);
    }
  }
}

This will save the example data into such XML file:

<?xml version="1.0" encoding="utf-8"?>
<ArrayOfKeyValueOfStringExampleDataClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <KeyValueOfStringExampleDataClass>
    <Key>First</Key>
    <Value>
      <Name>John</Name>
      <Surname>Doe</Surname>
    </Value>
  </KeyValueOfStringExampleDataClass>
  <KeyValueOfStringExampleDataClass>
    <Key>Second</Key>
    <Value>
      <Name>Foo</Name>
      <Surname>Bar</Surname>
    </Value>
  </KeyValueOfStringExampleDataClass>
</ArrayOfKeyValueOfStringExampleDataClass>

The example code does not solve any exceptions and invalid data.

  • Thanks for showing a replicable example. I added some details about the structure of my dictionary in the question above so it would be very helpful to see how the methods of the static class MySerializer should be changed in order to work with my dictionary. – mickG Dec 12 '14 at 16:47
  • @mickG Then you need to change only loading from the file to `myData = MySerializer.LoadFromXml(fileName);` since the class MySerializer is generic. The XML file will then have different structure of course. – Jindřich Pergler Dec 15 '14 at 09:48
  • Btw why do you use `itemdata` instead of `ItemData` as a name of the class? Overall convention in C# is CamelCaseName. The same for the properties. – Jindřich Pergler Dec 15 '14 at 09:50