Tuesday, January 18, 2011

Using LINQ to XML

LINQ to XML

Using LINQ to XML

Here I would like to explain how to use LINQ to Query XML and XML Objects. As we know, XML is extensively used because of its popularity. XML provides data in a more accurate, flexible, and adaptable way.
LINQ is more a query tool to Query different type of Data. Either it can used to query different types of Objects, SQL Data, and XML Data etc.
I have already given sample how to query Objects; here I am going to use XML data instead.
Creating XML Tree using LINQ
private void btnCreate_Click(object sender, EventArgs e)
        {
            try
            {
                //Creating XML Tree using the LINQ to XML Object and Save that in XML file

                XDocument doc = new XDocument();
                XElement contactsList =
                     new XElement("Contacts",
                             new XElement("Contact",
                             new XElement("Name", "Kapil"),
                                 new XElement("Phone", "206-555-0144",
                                 new XAttribute("Type", "Home")),
                                 new XElement("Phone", "425-555-0145",
                                 new XAttribute("Type", "Work")),
                                 new XElement("Address",
                                 new XElement("Street1", "300 Colonial Centre Pkwy"),
                                 new XElement("City", "Roswell"),
                                 new XElement("State", "GA"),
                                 new XElement("Postal", "30076")
                                 )
                              ),
                             new XElement("Contact",
                             new XElement("Name", "Yashu"),
                                 new XElement("Phone", "206-555-0144",
                                 new XAttribute("Type", "Home")),
                                 new XElement("Phone", "425-555-0145",
                                 new XAttribute("Type", "Work")),
                                 new XElement("Address",
                                 new XElement("Street1", "300 Colonial Centre Pkwy"),
                                 new XElement("City", "Roswell"),
                                 new XElement("State", "GA"),
                                 new XElement("Postal", "30076")
                                 )
                              )
                          );

                // Save the contact in XML file
                contactsList.Save("C:\\Save.xml");
            }
            catch (XmlException ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

In above piece of code, I am using XML Object to create XML tree using LINQ. You can use the XML DOM also to create the tree, but using the LINQ XML it is more efficient and faster. It is faster because LINQ to XML provides an in-memory XML programming interface.
Functional construction uses the XElement and XAttribute constructors to build an XML tree. Here we constructed the XML tree using the LINQ to XML functional construction.
Show XML Data Using LINQ
Here I am Using LINQ to show (display) the XML Data from the XML file. Below is the Form I will be using throughout this article. 


Designer Code
I am just showing the name of the fields from the designer, You can create the form and use the following name.

     this.richTextBox1 = new System.Windows.Forms.RichTextBox();
            this.btnShow = new System.Windows.Forms.Button();
            this.btnCreate = new System.Windows.Forms.Button();
            this.lblName = new System.Windows.Forms.Label();
            this.lblPhone = new System.Windows.Forms.Label();
            this.label3 = new System.Windows.Forms.Label();
            this.label4 = new System.Windows.Forms.Label();
            this.label5 = new System.Windows.Forms.Label();
            this.label1 = new System.Windows.Forms.Label();
            this.label2 = new System.Windows.Forms.Label();
            this.txtName = new System.Windows.Forms.TextBox();
            this.txtPhoneWork = new System.Windows.Forms.TextBox();
            this.txtPhoneHome = new System.Windows.Forms.TextBox();
            this.txtStreet = new System.Windows.Forms.TextBox();
            this.txtCity = new System.Windows.Forms.TextBox();
            this.txtState = new System.Windows.Forms.TextBox();
            this.txtPin = new System.Windows.Forms.TextBox();
            this.btnShow1 = new System.Windows.Forms.Button();
            this.SuspendLayout();

private void btnShow_Click(object sender, EventArgs e)
        {
            // Load the XML file using XElement, you can load the xml with different object also
            // XMLReader can also be used to load or read the xml
            // In following we are searching the xml which has the element name=Kapil and get the elment for that Node
            // Now we get the filltered data which is another set of xml (element), now you can use the IEnuramble to enumarte and display the each
            // Item in text field or where you need that.

            XElement contacts = XElement.Load("C:\\Save.xml");

            XElement filterName = new XElement("FilteringByName",
                              from contact in contacts.Elements("Contact")
                              where (string)contact.Element("Name").Value == "Kapil"
                              select new XElement("Contact", contact.Elements()
                            )
                            );
            richTextBox1.Text = filterName.ToString();
        }

In the above piece of code, we are loading the XML file using XElement LINQ Object. You can show whole XML but I am filtering the XML Data based on the Name element. To filter the data I am using LINQ to Query the XML data based on name.
As you see in code, it is like your SQL Query where you are looking into the XML with where clause to filter out the data. Select has been used to return the Element Data for that name specified in where clause.
The result will be shown in Text filed as
 
    Kapil
    206-555-0144
    425-555-0145
   
      300 Colonial Centre Pkwy
      Roswell
      GA
      30076
   
 
 



Show Contact Information
Query Element
As show in the above screen I am showing the contact information in each field from XML Data. In traditional XML DOM Object that can be accomplished by using the XPath or selecting each node from XML Element.
But here we are going to use the LINQ to query the each node of the XML element and display in the appropriate filed.
private void ShowContact(XElement element)
{
XElement contactname = new XElement("Name", from name in element.Element("Contact").Elements("Name")
select new XElement("Name",name.Value));

var contactphonew = (from phone in element.Element("Contact").Elements("Phone")
where (string)phone.Attribute("Type") == "Work"
select phone);

XElement contactphoneh = new XElement("PhoneHome",from phone in element.Element("Contact").Elements("Phone")
where (string)phone.Attribute("Type") == "Home"
select new XElement("Phone",phone.Value));

IEnumerable<XElement> contactaddress = from name in element.Element("Contact").Elements("Address")
select name;

txtName.Text = contactname.Value;
txtPhoneWork.Text = ((XElement)contactphonew.First()).Value;
txtPhoneHome.Text = contactphoneh.Value;

foreach(XElement address in contactaddress)
{
txtStreet.Text = address.Element("Street1").Value;
txtCity.Text = address.Element("City").Value;
txtState.Text = address.Element("State").Value;
txtPin.Text = address.Element("Postal").Value;
}

}

LINQ is as powerful as shown in above code, the pattern for each query is similar.  Here I have used the different approaches to use the LINQ. Drilling down to each element and getting their values.
Using Object Value to Store the Values
Here I am going to show different mechanism to Query the Element and Store in Class Object (Object Values).
To make it simple I have a Class with some property
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace LinqToXML
{
    public class ContactDataObject
    {
        public string Name { get; set; }
        public string PhoneHome { get; set; }
        public string PhoneWork { get; set; }
        public string Street { get; set; }
        public string City { get; set; }
        public string State { get; set; }
        public string Postal { get; set; }
    }
}

LINQ Query
Now we can use LINQ to query the XML file and store the relevant data to object. The mechanism is same to query the XML using somewhat similar syntax. The difference here is we are storing the data while we are queering the XML file for that person name.
public ContactDataObject SetContact(XElement element) {

            ContactDataObject data = (ContactDataObject)(from contact in element.Descendants("Contact")
select new ContactDataObject()
{
Name = contact.Element("Name").Value,
Street = contact.Element("Address").Element("Street1").Value,
City = contact.Element("Address").Element("City").Value,
State = contact.Element("Address").Element("State").Value,
Postal = contact.Element("Address").Element("Postal").Value,
PhoneHome = (from phone in contact.Elements("Phone")
where (string)phone.Attribute("Type") == "Home"
select new XElement("Phone",phone.Value)).First().Value
}).FirstOrDefault();
return data;
}

In above we are passing the Element and storing the values to property of ContactDataObject class. Below is the code how we are calling the above function and displaying the data to field.
private void btnShow1_Click(object sender, EventArgs e) {

            XElement contacts = XElement.Load("C:\\Save.xml");

            XElement filterName = new XElement("FilteringByName",
                              from contact in contacts.Elements("Contact")
                              where (string)contact.Element("Name").Value == "Kapil"
                              select new XElement("Contact", contact.Elements()
                            )
                            );
            richTextBox1.Text = filterName.ToString();
            ContactDataObject data = SetContact(filterName);
            txtName.Text = data.Name;
            txtPhoneHome.Text = data.PhoneHome;
            txtStreet.Text = data.Street;
            txtCity.Text = data.City;
            txtState.Text = data.State;
            txtPin.Text = data.Postal;
        }

I hope that will guide most of the people how to use the LINQ to query or get the data from XML file. I have taken simple scenario for understanding.




Wednesday, September 15, 2010

Use of Delegate and Lambda Expression

Use of Delegate and Lambda Expression


There are remarkable changes in the C# from the 1.0 Version. C# 2.0 and C# 3.0 has introduced lots of new thing they way we handle the things. Here I would like to discuss about the use of Delegates and Lambda Expression’s. Lambda Expressions has been introduced in C# 3.0 (2008).

What is Delegate?


"A delegate is a reference type that represents a method with a specific signature and return type."

Delegates allow you to pass a function to another function. As a concept, it's similar to functions as first-class types in functionally languages. A typical delegate usage is as a callback for asynchronous method calls.
A delegate in C# is similar to a function pointer in C or C++. Using a delegate allows the programmer to encapsulate a reference to a method inside a delegate object. The delegate object can then be passed to code which can call the referenced method, without having to know at compile time which method will be invoked.

Call a Function directly - No Delegate

In most cases, when we call a function, we specify the function to be called directly. If the class MyClass has a function named Process, we'd normally call it like this (SimpleDelegateSample.cs):
namespace NoDelegate
{
    public class MyClass
    {
        public void Invoke() {
            Console.WriteLine("Invoke () begin");
            Console.WriteLine("Invoke () end");
        }
    }

    public class Test
    {
        static void Main(string[] args) {
            MyClass myClass = new MyClass();
            myClass.Invoke();
        }
    }
}

That works well in most situations. Sometimes, however, we don't want to call a function directly - we'd like to be able to pass it to somebody else so that they can call it. This is especially useful in an event-driven system such as a graphical user interface, when I want some code to be executed when the user clicks on a button, or when I want to log some information but can't specify how it is logged.

Call a Function - Delegate


namespace BasicDelegate
{
    // Declaration
    public delegate void SimpleDelegate();

    class TestDelegate
    {
        public static void MyFunc() {
            Console.WriteLine("I was called by delegate ...");
        }

        public static void Main() {
            // Instantiation
            SimpleDelegate simpleDelegate = new SimpleDelegate(MyFunc);

            // Invocation
            simpleDelegate();
        }
    }
}

A delegate can be initialized with inline code, called an "anonymous method." This    method takes a string as an input parameter.
namespace ConsoleApplication1
{
    class Program
    {
        delegate void Print(string s);
        static void Main(string[] args) {

            Print p = delegate(string s) { Console.WriteLine("We are printing" + s); };
            p("Hello");

            Console.Read();
        }
    }
}

What is Lambda Expression?


A lambda expression simply defines an anonymous function. A function is something that takes one or more parameters (just as a method does)
In C# 3, the "=>" syntax is used to write a lambda expression. You place the parameters to the left of the arrow and the expression to compute to the right. The lambda expression can be assigned to delegate as shown below

namespace ConsoleApplication1
{
    class Program
    {
        delegate void Print(string s);
        static void Main(string[] args) {

            Print p = delegate(string s) { Console.WriteLine("We are printing" + s); };
            p("Hello");


            Console.WriteLine("Lambda Expression ");
            Print p1 = (x) => { Console.WriteLine("We are printing using Lambda " + x); };
                p1("Wow, it's Cool");
            Console.Read();
        }
    }
}

Below is the Sample Code which shows use of delegate and lambda expression. I have take here the Type List so that I can show the different way of using “anonymous function”

Product.cs


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication
{
    class Product
    {
        public string Name { get; private set; }
        public decimal Price { get; private set; }

        public Product(string name, decimal price)
        {
            Name = name;
            Price = price;
        }

        public Product() { }
        public static List<Product> GetProductInformation()
        {
            List<Product> prod = new List<Product>();
            prod.Add(new Product("Soap", 11));
            prod.Add(new Product("Toothpaste", 10));
            prod.Add(new Product("Brush", 12));
            prod.Add(new Product("Shampoo", 10));

            return prod;
        }

        public override string ToString()
        {
            return string.Format("{0}: {1}", Name, Price);
        }

    }
}

Implemented the IComparer Interface to sort the product.

CompareProduct.cs


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication
{
    class CompareProduct: IComparer<Product>
    {

        #region IComparer Members

        public int Compare(Product x, Product y) {
            return x.Name.CompareTo(y.Name);
        }

        #endregion
    }
}

Main Program

Program.cs


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication
{
    class Program
    {
        static void Main(string[] args)
        {

            Console.WriteLine("Product .......");
            foreach (Product pro in Product.GetProductInformation())
            {
                Console.WriteLine(pro.ToString());

            }

            Console.WriteLine(" Using IComparer Interface to Compare");
            List<Product> product = Product.GetProductInformation();
            product.Sort(new CompareProduct());
            Console.WriteLine();
            Console.WriteLine("Sorting 1.......");
            foreach (Product pro in product)
            {
                Console.WriteLine(pro.ToString());

            }
           
            List<Product> product1 = Product.GetProductInformation();
            Console.WriteLine();
            Console.WriteLine("Sorting 2.......");
            foreach (Product pro in product1.OrderBy(p => p.Name))
            {
                Console.WriteLine(pro.ToString());

            }
            List<Product> product2 = Product.GetProductInformation();
            product2.Sort((first, second) => first.Name.CompareTo(second.Name));
            Console.WriteLine();
            Console.WriteLine("Sorting 3.......");
            foreach (Product pro in product2)
            {
                Console.WriteLine(pro.ToString());

            }
            Predicate<Product> criteria = delegate(Product p)
            {
                return p.Price == 10;
            };

            List<Product> product3 = Product.GetProductInformation();
           List<Product> matches = product3.FindAll(criteria);
            Console.WriteLine("Finding with price 10.......");

            Action<Product> print = delegate(Product p)
            {
                Console.WriteLine(p);
            };
            matches.ForEach(print);

            Console.WriteLine("Lamda expression with Printing & Finding with price > 10.......");
            List<Product> products = Product.GetProductInformation();
            foreach (Product product4 in products.Where(p => p.Price > 10))
            {
                Console.WriteLine(product4);
            }

            Console.WriteLine("Delegate to Printing & Finding with price == 10.......");
            List<Product> finalProduct = Product.GetProductInformation();
            finalProduct.FindAll((delegate(Product p) { return p.Price == 10; })).ForEach((delegate(Product p) { Console.WriteLine(p); }));
            Console.Read();
        }
    }
}