Now I’m not going to lie, getting started with LINQ if you’re a non-professional programmer like myself can be a journey. It is however, a journey well worth taking..
Recently I decided to create my own version of the Vista Game Launcher script which lets you annihilate all those random processes and services that hang around on Vista like thugs outside a corner-shop. Even though my machine is great for gaming after my recent upgrade, it helps gain even more precious resources for the game to use. The script has a few problems though:
- It takes a degree is Computer Science to even deduce how to add a game to the list of games you can launch.
- Like I said above, it annihilates everything that isn’t needed and the only way to restore what was closed/stopped is by restarting the entire computer.
While it’s not very efficient or user-friendly, it does the job. As usual though, like always, I want more. So I ended up creating another whacky program to do it all for me. I’ve always struggled with programming XML routines in VB.NET and now C#. I don’t know why, but I’ve just never been able to get my head around serialisation and all that business. Then along comes LINQ, swaggering in the door like a cocky little kid who knows more than you and is half your age (I’m 22 by the way).
So, I needed a way to quickly read and change an XML file, which I use to define a “launch profile”. These profiles define the options for the specific set of games and/or programs which will be shown in the “launch list”, so they’re going to be altered and read quite often in the process of using the program. This is where LINQ comes in.
Using LINQ
For this little article, I’ll be using the following XML:
<?xml version="1.0" encoding="utf-8" ?>
<LaunchProfile name="Default">
<Options>
<CloseExplorer value="true">
<DisableGlass value="false" />
<DisableThemes value="false" />
<DisableEverything value="true" />
</CloseExplorer>
<CloseProcesses value="true" />
<CloseServices value="true" />
<DashboardMode value="true" />
</Options>
</LaunchProfile>
To begin reading from an XML file stored locally, you have two options: use the XDocument class, or the XElement class. Using the XDocument class in this scenario is a bit pointless as all it does is encapsulate the XML file as an XElement object. Save XDocument for other, more low-level activities young man/woman/thing!
So, first we define an XElement object to much up the entire XML File, and use the ubiquitous ‘Load’ method to get all our information into the object:
XElement xe_XmlFile = XElement.Load(xmlFilePath);
Now if we add a breakpoint after this code and press F5 in Visual Studio and debug our program, you’ll notice that the xe_XmlFile variable now contains all the information from the root-node onwards in our XML File. Lovely jubbly.
Just like above, you now have two options: you can iterate through xe_XmlFile using the usual foreach looping OR you can go the new-school route: LINQ Queries. In this little article I’ll show you the LINQ Query route, for a few reasons:
- LINQ Queries are extremely easy to learn, but just as hard to master.
- They resemble SQL queries almost to a tee, but are much more intuitive.
- You can gather huge amounts of data in only two lines of code.
We first want to get the name attribute of the <LaunchProfile> tag so we know what profile we’re dealing with. This is almost criminally easy:
XElement xe_XmlFile = XElement.Load(g_defaultXml);
// Get the name of this <LaunchProfile>:
string xs_ProfileName = xe_XmlFile.FirstAttribute.Value.ToString();
As you can see, we’ve already loaded the XML file into our XElement object, then we’ve declared a new string to hold our profile name. Often, you’ll only use one attribute within a given element like I have, so using the FirstAttribute property will enable you to retrieve it’s value easily. Once this is done, we can use the same method to get the values of the elements within the <Options> node, but this time, we’re going to select a specific element, using it’s XName, and then get it’s value:
XElement xe_Options = xe_XmlFile.Element("Options");
bool b_closeProcs = bool.Parse(
xe_Options.Element("CloseProcesses").
FirstAttribute.Value);
Of course, in our situation, we have more than one value that we need to determine, so we the most efficient to do this would be to use another one of those handy LINQ Queries:
var xe_opVals = (from el in xe_Options.Descendants()
select new
{
Option = el.Name,
Value = bool.Parse(el.FirstAttribute.Value)
});
foreach (var opVal in xe_opVals)
{
Console.WriteLine("Option: {0}, Value: {1}",
opVal.Option, opVal.Value);
}
Above you can see I’ve made use of one very cool feature of LINQ and that’s generic properties. You can create properties for any value returned by a query on the fly, which can then be accessed via your anonymous type (xe_opVals) anywhere in your code. Awesome.
And there you have it! A perfectly working skeleton of an XML based custom settings class using LINQ to XML. Your brain should be buzzing by now (in a good way I hope) so I’ll let you figure out how to implement it in your own way. Hopefully in the near future, I’ll be expanding on the topic to include some of the more advanced functions of LINQ.
Happy coding!