2

Lets say I have an item, which has fields(properties)

  1. Location
  2. Average value
  3. Usability

And I have 10-15 items, whose values I want to be predefined, or written somewhere and then loaded into code to be used.

Which would be the best practice for it?

These would be constants, just start up parameters, which will not be modified during application lifecycle.

Robert Harvey
  • 178,213
  • 47
  • 333
  • 501
Jaanus
  • 16,161
  • 49
  • 147
  • 202

5 Answers5

3

You can serialize and deserialize a List<Item> to and from an XML file using this helper class:

public static class XmlHelper
{
    // Specifies whether XML attributes each appear on their own line
    const bool newLineOnAttributes = false;

    public static bool NewLineOnAttributes { get; set; }
    /// <summary>
    /// Serializes an object to an XML string, using the specified namespaces.
    /// </summary>
    public static string ToXml(object obj, XmlSerializerNamespaces ns)
    {
        Type T = obj.GetType();

        var xs = new XmlSerializer(T);
        var ws = new XmlWriterSettings { Indent = true, NewLineOnAttributes = newLineOnAttributes, OmitXmlDeclaration = true };

        var sb = new StringBuilder();
        using (XmlWriter writer = XmlWriter.Create(sb, ws))
        {
            xs.Serialize(writer, obj, ns);
        }
        return sb.ToString();
    }

    /// <summary>
    /// Serializes an object to an XML string.
    /// </summary>
    public static string ToXml(object obj)
    {
        var ns = new XmlSerializerNamespaces();
        ns.Add("", "");
        return ToXml(obj, ns);
    }

    /// <summary>
    /// Deserializes an object from an XML string.
    /// </summary>
    public static T FromXml<T>(string xml)
    {
        XmlSerializer xs = new XmlSerializer(typeof(T));
        using (StringReader sr = new StringReader(xml))
        {
            return (T)xs.Deserialize(sr);
        }
    }

    /// <summary>
    /// Serializes an object to an XML file.
    /// </summary>
    public static void ToXmlFile(Object obj, string filePath)
    {
        var xs = new XmlSerializer(obj.GetType());
        var ns = new XmlSerializerNamespaces();
        var ws = new XmlWriterSettings { Indent = true, NewLineOnAttributes = NewLineOnAttributes, OmitXmlDeclaration = true };
        ns.Add("", "");

        using (XmlWriter writer = XmlWriter.Create(filePath, ws))
        {
            xs.Serialize(writer, obj);
        }
    }

    /// <summary>
    /// Deserializes an object from an XML file.
    /// </summary>
    public static T FromXmlFile<T>(string filePath)
    {
        StreamReader sr = new StreamReader(filePath);
        try
        {
            var result = FromXml<T>(sr.ReadToEnd());
            return result;
        }
        catch (Exception e)
        {
            throw new Exception(e.InnerException.Message);
        }
        finally
        {
            sr.Close();
        }
    }
}

Usage:

XmlHelper.ToXmlFile(myList, @"c:\folder\file.xml");

var list = XmlHelper.FromXmlFile<List<Item>>(@"c:\folder\file.xml");
Robert Harvey
  • 178,213
  • 47
  • 333
  • 501
2

Your options will be:

  1. XML - one of your tags actually
  2. Database
  3. Binary File

Store the objects and the read them in your code.

Write XML code example:

public void WriteXML()
{
    Book overview = new Book();
    overview.title = "Serialization Overview";
    System.Xml.Serialization.XmlSerializer writer = 
        new System.Xml.Serialization.XmlSerializer(typeof(Book));

    System.IO.StreamWriter file = new System.IO.StreamWriter(
        @"c:\temp\SerializationOverview.xml");
    writer.Serialize(file, overview);
    file.Close();
}

Read XML code example:

public void Read(string  fileName)
{
    XDocument doc = XDocument.Load(fileName);

    foreach (XElement el in doc.Root.Elements())
    {
        Console.WriteLine("{0} {1}", el.Name, el.Attribute("id").Value);
        Console.WriteLine("  Attributes:");
        foreach (XAttribute attr in el.Attributes())
            Console.WriteLine("    {0}", attr);
        Console.WriteLine("  Elements:");

        foreach (XElement element in el.Elements())
            Console.WriteLine("    {0}: {1}", element.Name, element.Value);
    }
}
Mortalus
  • 10,574
  • 11
  • 67
  • 117
  • First option is most acceptable, thats why the tag, cause was thinkin in same direction, what about just creating them in `*.cs` file with setters and adding them to somekind of global static collection? – Jaanus Mar 06 '13 at 20:27
  • you could use static object from the item class but, what if you would want to add another item later .. you will have to recompile (rebuild) the whole project ??? that will not be a good suggestion if the project suppose to be used by other people :) – Mortalus Mar 06 '13 at 20:29
  • While this are viable options, none of them is the most optimal for this case. a DB doesn't seem like the best place for `CONSTANT` data. XML requires the XML file stored somewhere with the deployed binaries and also consumes start-up time to be loaded. The same for binary file. – Federico Berasategui Mar 06 '13 at 20:29
  • 2
    Five minutes after you hard code it in your app, you'll suddenly need to change them, if your lucky.If your unlucky, the day after you deploy. – Mike C. Mar 06 '13 at 20:30
  • Sotring them in an XML file provides much flexibility to create more of these objects without recompiling the code, sorry but I disagree. performance wise if there are less than a few hundreds of items i think that an XML will not have any performance hit... – Mortalus Mar 06 '13 at 20:31
  • Forgot to mention that this application is only for me, so recompiling it would be no trouble. – Jaanus Mar 06 '13 at 20:50
1

ApplicationSettings would be a good fit for startup constants.

Ed Power
  • 8,310
  • 3
  • 36
  • 42
  • 1
    I believe this is not great with complex objects. Correct me if I'm wrong. – Jaanus Mar 06 '13 at 21:07
  • You could serialize it into a string, or create individual properties for each of your item's fields and construct from them. – Ed Power Mar 06 '13 at 21:57
0

What you're describing sounds like the perfect use case for T4

You could add a T4 template to your project that reads XML data (in design-time within Visual Studio) and generates *.cs files with your static content. If you ever need to modify the data, just modify the XML file and click the Transform All Templates button in the Solution Explorer.

Keep in mind that this will require you to recompile and redeploy the application if you need to modify those contents. If that is the case, then the solution provided by @Mortalus is the best option.

Federico Berasategui
  • 43,562
  • 11
  • 100
  • 154
0

I’d use web.config and store this in app settings area and then create one class that will read these retrieve it as a list.

Here is how it could look in web config and C# code.

 <appSettings>      
    <add key="location_1" value="123"/>
    <add key="avgValue_1" value="123"/>
    <add key="usability_1" value="123"/>
    <add key="location_2" value="123"/>
    <add key="avgValue_2" value="123"/>
    <add key="usability_2" value="123"/>
    <add key="count" value="2"/>
 </appSettings>

public class SomeClass
{
private string location;
private double avgValue;
private int usability;

public string Location 
{
    get { return location; }
    set { location = value; }
}
public double AvgValue
{
    get { return avgValue; }
    set { avgValue = value; }
}
public int Usability
{
    get { return usability; }
    set { usability = value; }
}
}

public class Config
{
public static List<SomeClass> Items
{
    get
    {
        List<SomeClass> result = new List<SomeClass>();

        for (int i = 1; i <= Convert.ToInt32(WebConfigurationManager.AppSettings["count"]); i++)
        {
            SomeClass sClass = new SomeClass();
            sClass.AvgValue = Convert.ToDouble(WebConfigurationManager.AppSettings["avgValue_" + i.ToString()]);
            sClass.Location = WebConfigurationManager.AppSettings["location_" + i.ToString()];
            sClass.Usability = Convert.ToInt32(WebConfigurationManager.AppSettings["usability_" + i.ToString()]);
        }

        return result;
    }
}

}