Linq To XML: Generate Types with Nested Types using C#

In this article, we will have look at how can we generate Types with subtypes using Linq To XML

Suppose we have an XML file which holds information about Cars as their Model Name, Transmission details, Engine Details and some other information, like follows

<?xml version="1.0" encoding="utf-8" ?> 
<Cars>
 <Car Name = "Golf">
    <Transmission Type="Manual" Gears="5" />
    <Engine Type="diesel" Power="2000" />
 </Car>
 <Car Name = "Mazda">
    <Transmission Type="Automatic" Gears="4" />
    <Engine Type="Patrol" Power="2000" />
 </Car>
</Cars>

Now we have class named Car as Follows

    class Car
    {
        // struct Transmission
        public Transmission Transmission { get; set; }
        // struct Engine
        public Engine Engine { get; set; }
    }

Class car has two properties which are structs, Transmission and Engine

    struct Engine
    {
        // Type of Engine
        public string Type
        { get; set; }

        // Power of Engine
        public int Power
        { get; set; }
    }
    struct Transmission
    {
        // Type of Transmission
        public string Type
        { get; set; }

        // Type of Transmission
        public int Gears
        { get; set; }

        public override string ToString()
        { return Type + " " + Gears; }
    }

This is how we can parse the above XML document using XElement and Linq To XML and generate the required classes

                 // Load Document using XElement
                 XElement elements = XElement.Load("XMLFile.xml");

                 // using Linq To Xml parse and load Objects
                 List<Car> CarsList =
                 (from e in elements.Descendants("Car")
                 // get new Car object
                 select new Car
                 {
                     // get Name for the Car
                     Name = e.Attribute("Name").Value,

                     // get Transmission details for the Car
                     Transmission = new Transmission()
                     {
                         Type = e.Element("Transmission").Attribute("Type").Value,
                         Gears = Convert.ToInt32(e.Element("Transmission").Attribute("Gears").Value)
                     },
                     // get Engine details for the Car
                     Engine = new Engine()
                     {
                         Type = e.Element("Engine").Attribute("Type").Value,
                         Power = Convert.ToInt32(e.Element("Engine").Attribute("Power").Value)
                     }
                 }).ToList<Car>();

To work over the returned List of cars we can use many methods, one of which is foreach

            foreach (Car car in CarsList)
            {                
                Console.WriteLine(car.Name);                
                Console.WriteLine(car.Engine.Type);
                Console.WriteLine(car.Transmission.ToString());
                Console.WriteLine("--------------");  
            }

here is the output:

Advertisements

Using attributes in c#

In the .NET Framework there are many reasons to use attributes, like

  • Defining which classes are serializable
  • Choosing which methods are exposed in a Web service
  • As per definition at MSDN
    Attributes allow us to add descriptions to classes, properties, and methods at design time that can then be examined at runtime via reflection.”

    Consider this example:
    Say you have a class which has a method from older version which is still in use for any reason and now you have come up with a new version of the class which makes fantastic use of Generic List and LINQ and has a new method for similar purpose. You would like developers to prefer the new one provided in the later version of your library. How will you do that ? One way is to write in the documentation. A better way is to use attribute as follow.

    public class AccountsManager
        {
          [Obsolete("prefer GetAccountsList", true)]
          static Account[] GetAccounts( ) { }    
          static List<Account> GetAccountsList( ) { }      
        }
    

    If an obsolete method is used when the program is compiled, the developer gets this info and decides accordingly.

    AccountManager.GetAccounts() is obsolete: prefer GetAccountsList

    We may also create and add Custom Attributes as per requirements.

    References :

  • Use the advantages of custom attributes in your C# applications
  • Using Attributes in C#