1
\$\begingroup\$

I'm developing a WinForms app to manage some settings and profiles for multiple video games. The list of video games is specified by the user, and I'm trying to figure out how to properly maintain that list/collection throughout the lifetime of my application.

I decided on an XML file to manage the games list which looks like this:

<?xml version="1.0" encoding="utf-8" ?>
<Games>
  <Game>
    <Name>NBA 2K13</Name>
    <FolderPath>C:\Games\NBA2K13</FolderPath>
  </Game>
  <Game>
    <Name>First Person Shooter</Name>
    <FolderPath>C:\Games\FPS</FolderPath>
  </Game>
</Games>

It was suggested to me that I should not continually read/write to the XML file; instead, I should load the XML file into a collection (I'm using serialization for this), let the app work off of the collection, and then persist the collection back to the XML file when the app is closed. For the game collection class (Games), I'm also treating it as a hybrid "repository" (see the Add() method).

I came up with the following classes for that:

public class Game
    {
        [XmlElement("Name")]
        public string Name { get; set; }
        [XmlElement("FolderPath")]
        public string FolderPath { get; set; }

        public Game() {}

        public Game(string name, string folder)
        {
            Name = name;
            FolderPath = folder;
        }
    }

[XmlRootAttribute("Games")]
    public class Games
    {
        public Games()
        {
            Items = new List<Game>();
        }

        [XmlElement("Game")]
        public List<Game> Items { get; set; }

        public void Add(Game game)
        {
            if (!Items.Any(g => g.Name.EqualsIgnoreCase(game.Name)))
            {
                if (Directory.Exists(game.FolderPath))
                    Items.Add(game);
                else
                    MessageBoxUtil.ShowError("Invalid directory entered.");
            }
            else
                MessageBoxUtil.ShowError("Game names must be unique. " + game.Name + " already exists.");
        }
    }

This code seems to work fine, and loading/persisting the data is working as planned (I'd still appreciate suggestions on whether this is a good approach). What I'm struggling with is how to maintain that collection throughout the app's lifecycle. Right now, there are 2 forms that need access to this collection (Games class). Should the Games class be made static since the Items collection is derived from a single XML file and could possibly be considered global data? Would it be better to implement the singleton pattern and pass around a single instance of Games?

\$\endgroup\$
1
  • \$\begingroup\$ For now, I've added a 'GamesService' class as a singleton and had it load the 'Games' collection in the constructor. I moved the 'Add()' method to the service. Other suggestions are welcome. \$\endgroup\$ Commented Jun 25, 2015 at 18:13

1 Answer 1

2
\$\begingroup\$

Both a singleton solution and a static instance are acceptable. What I would recommend is that you add a static factory to Games, like:

public static Games LoadFromFile(String xmlFile);

You would call this near the top level of your application and then you would pass it into any of your other code that requires it. It's essentially dependency injection, in that you design the code that's going to use the Games object to have it injected it. It makes testing easier and it makes the design more flexible.

\$\endgroup\$
2
  • \$\begingroup\$ Thanks, this sounds like a good approach. There's also the question of when to actually persist the collection back to the XML file. I've tried to Google the best time to do this, but I'm coming up short. Perhaps in the Games destructor? In the main FormClosing event? \$\endgroup\$ Commented Jun 27, 2015 at 4:39
  • \$\begingroup\$ You could persist when your app exits, but that means if there's a crash then the changes aren't saved. Games could fire a change event that would cause the owner to save it to disk. \$\endgroup\$ Commented Jun 29, 2015 at 15:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.