Sets of data can be stored in many different locations, such as configuration files. You want to be able to query your configuration files for sets of information.
Use LINQ to query against the configuration sections. In the example below, this is done by retrieving all chapter titles with even numbers and the word "and" in the title from the custom configuration section containing chapter information:
CSharpRecipesConfigurationSection recipeConfig = ConfigurationManager.GetSection("CSharpRecipesConfiguration") as CSharpRecipesConfigurationSection; var expr = from ChapterConfigurationElement chapter in recipeConfig.Chapters.OfType<ChapterConfigurationElement>() where (chapter.Title.Contains("and")) && ((int.Parse(chapter.Number) % 2) == 0) select new { ChapterNumber = "Chapter " + chapter.Number, chapter.Title }; foreach (var chapterInfo in expr) { Console.WriteLine(chapterInfo.ChapterNumber + ": " + chapterInfo.Title); }
The configuration section being queried looks like this:
<CSharpRecipesConfiguration CurrentEdition="3"> <Chapters> <add Number="1" Title="Language Integrated Query (LINQ)"/> <add Number="2" Title="Strings and Characters"/> <add Number="3" Title="Classes and Structures"/> <add Number="4" Title="Generics"/> <add Number="5" Title="Collections"/> <add Number="6" Title="Iterators, Partial Types and Partial Methods"/> <add Number="7" Title="Exception Handling"/> <add Number="8" Title="Diagnostics"/> <add Number="9" Title="Delegates, Events, and Functional Programming"/> <add Number="10" Title="Regular Expressions"/> <add Number="11" Title="Data Structures & Algorithms"/> <add Number="12" Title="Filesystem I/O"/> <add Number="13" Title="Reflection"/> <add Number="14" Title="Web"/> <add Number="15" Title="XML"/> <add Number="16" Title="Networking"/> <add Number="17" Title="Security"/> <add Number="18" Title="Threading and Synchronization"/> <add Number="19" Title="Toolbox"/> <add Number="20" Title="Numbers & Enumerations"/> </Chapters> <Editions> <add Number="1" PublicationYear="2004"/> <add Number="2" PublicationYear="2006"/> <add Number="3" PublicationYear="2007"/> </Editions> </CSharpRecipesConfiguration>
The output from the query is:
Chapter 2: Strings and Characters Chapter 6: Iterators, Partial Types and Partial Methods Chapter 18: Threading and Synchronization
Configuration files in .NET play a significant role in achieving manageability and ease of deployment for .NET-based applications. It can be challenging to get all of the various settings right in the hierarchy of configuration files that can affect an application, so understanding how to write utilities to programmatically check configuration file settings is of great use during development, testing, deployment, and ongoing management of an application.
Even though the ConfigurationElementCollection
class (the base of sets of data inconfiguration files) only supports IEnumerable
and not IEnumerable<T>
, we can stilluse it to get the elements we need by using the OfType<ChapterConfigurationElement>
method on the collection, which selects elements of that type from the collection:
var expr = from ChapterConfigurationElement chapter in recipeConfig.Chapters.OfType<ChapterConfigurationElement>()
ChapterConfigurationElement
is a custom configuration section class that holds the chapter number and title:
/// <summary> /// Holds the information about a chapter in the configuration file /// </summary> public class ChapterConfigurationElement : ConfigurationElement { /// <summary> /// Default constructor /// </summary> public ChapterConfigurationElement() { } /// <summary> /// The number of the Chapter /// </summary> [ConfigurationProperty("Number", IsRequired=true)] public string Number { get { return (string)this["Number"]; } set { this["Number"] = value; } } /// <summary> /// The title of the Chapter /// </summary> [ConfigurationProperty("Title", IsRequired=true)] public string Title { get { return (string)this["Title"]; } set { this["Title"] = value; } } }
This technique can be used on the standard configuration files such as machine.config
as well. This example determines which sections in machine.config
require access permissions. For this collection, OfType<ConfigurationSection>
is used, as this is a standard section:
System.Configuration.Configuration machineConfig = ConfigurationManager.OpenMachineConfiguration(); var query = from ConfigurationSection section in machineConfig.Sections. OfType<ConfigurationSection>() where section.SectionInformation.RequirePermission select section; foreach (ConfigurationSection section in query) { Console.WriteLine(section.SectionInformation.Name); }
The sections detected will look something like this:
system.data windows system.webServer mscorlib system.data.oledb system.data.oracleclient system.data.sqlclient configProtectedData satelliteassemblies system.data.dataset startup system.data.odbc system.diagnostics runtime system.codedom system.runtime.remoting assemblyBinding system.windows.forms
Get C# 3.0 Cookbook, 3rd Edition now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.