Wednesday, April 30, 2008

LINQ to XML - Namespaces

Adding on to yesterday's post, you might come across xml that has a namespace defined. You'll have to handle this with the XNamespace object.
XML with namespace:
<?xml version="1.0" standalone="yes"?>
<MyDataSet xmlns="http://tempuri.org/MyDataSet.xsd">
  <Person>
    <PersonId>1</PersonId>
    <PersonName>Mark</PersonName>
  </Person>
  <Person>
    <PersonId>2</PersonId>
    <PersonName>Matt</PersonName>
  </Person>
</MyDataSet>
Querying the XML:
XDocument ds = XDocument.Load(Resources.SimpleXmlFileWithNamespacePath);
XNamespace ns = "http://tempuri.org/MyDataSet.xsd";
XName xNamePerson = ns + "Person";
XName xNamePersonName = ns + "PersonName";

var personNames = from person in ds.Descendants(xNamePerson)
              select new
              {
                  PersonName = person.Element(xNamePersonName).Value
              };
The XName class provides a way to combine a namespace and an element name.

More Info: MSDN: XNamespace Class
MSDN: XName Class

Tuesday, April 29, 2008

LINQ to XML

There's a lot you can do with LINQ to XML. It will be your alternative to selecting xml nodes using XPath queries. I'm going to show you just a little bit at a time.

Say you wanted to get all PersonName values from this xml:
<Persons>
  <Person>
    <PersonId>1</PersonId>
    <PersonName>Mark</PersonName>
  </Person>
  <Person>
    <PersonId>2</PersonId>
    <PersonName>Matt</PersonName>
  </Person>
</Persons>
You can simply write your LINQ like this:
XDocument ds = XDocument.Load("PersonsFile.xml");

var persons = from eachPerson in ds.Descendants("Person") 
select new 
{
    PersonName = eachPerson.Element("PersonName").Value
};
This is two lines of code. Notice the semicolon at the very end.

XDocument is like your new XmlDocument class. It loads an xml file.
LINQ is then used to find all elements (descendants) that are named "Person".

So what the heck is happening with that select new? Remember the post on anonymous types? That's what this LINQ to XML is creating; a collection of anonymous types (classes). The breakdown of what this LINQ statement is saying:
1. Give me a collection of elements that match "Person" which you can reference from the eachPerson variable.
2. Create an anonymous class and add a property called "PersonName".
3. "PersonName" is assigned a value from the eachPerson match.
4. Now add that new anonymous class to the var collection called "persons".

The result is a collection of typed objects that you can iterate through later on:
List<string> array = new List<string>();
foreach (var person in persons)
{
    array.Add(person.PersonName);
}

This is a whole different shift in thinking. To get used to it I suggest you write some code and create a bunch of anonymous classes until you are comfortable with that concept. Create anonymous classes, add properties. Access and use those properties and so on. Once you feel good and comfortable with that you can move on to learning more about LINQ.
More Info: MSDN:

Friday, April 25, 2008

XmlWriter

To create this in code:
<?xml version="1.0" encoding="utf-16"?><Person><FirstName>Mark</FirstName><LastName>Moeykens</LastName></Person>
You can code it this way:
StringBuilder sb = new StringBuilder();
using(XmlWriter writer = XmlTextWriter.Create(sb))
{
    writer.WriteStartElement("Person");
    writer.WriteElementString("FirstName", "Mark");
    writer.WriteElementString("LastName", "Moeykens");
    writer.WriteEndDocument();
}
Console.Write(sb.ToString());
The
<?xml version="1.0" encoding="utf-16"?>
bugs me though. I never seem to have a use for it in my code so let's get rid of it.

To do that, we have to introduce some settings for our writer using the XmlWriterSettings class then pass it into the XmlTextWriter.Create method.
XmlWriterSettings settings = new XmlWriterSettings();
settings.OmitXmlDeclaration = true;

StringBuilder sb = new StringBuilder();
using(XmlWriter writer = XmlTextWriter.Create(sb, settings))
{
    writer.WriteStartElement("Person");
    writer.WriteElementString("FirstName", "Mark");
    writer.WriteElementString("LastName", "Moeykens");
    writer.WriteEndDocument();
}
Console.Write(sb.ToString());
Output:
<Person><FirstName>Mark</FirstName><LastName>Moeykens</LastName></Person>
That's better. Now let's add another setting to get the elements on their own line and indented:
XmlWriterSettings settings = new XmlWriterSettings();
settings.OmitXmlDeclaration = true;
settings.Indent = true;

StringBuilder sb = new StringBuilder();
using(XmlWriter writer = XmlTextWriter.Create(sb, settings))
{
    writer.WriteStartElement("Person");
    writer.WriteElementString("FirstName", "Mark");
    writer.WriteElementString("LastName", "Moeykens");
    writer.WriteEndDocument();
}
Console.Write(sb.ToString());
Output:
<Person>
  <FirstName>Mark</FirstName>
  <LastName>Moeykens</LastName>
</Person>
There we go, this looks much better!

More Info: MSDN: Creating XML Writers

Thursday, April 24, 2008

Predicate Delegate

To pose a problem, let's create a strongly typed list of the Person class:
public class Person
{
    public string FirstName { get; set; }
}

// ...

List<Person> people = new List<Person>
              {
                  new Person("Mark"),
                  new Person("Rod"),
                  new Person("Matt"),
                  new Person("Rich"),
                  new Person("Jake")
              };
I used a collection initializer to populate a new typed generic List.

Ok, so how would you do a search in that collection and return the Person class that represents "Rod"? Luckily this generic list class has 5 different Find type methods (9 if you count the overloads).

Take a look at them though. They take a "Predicate". What the heck is this "Predicate"?

The word "predicate" is a term used in the subject of Logic that basically means
"to say something is true or false"
.

A predicate in .NET is a delegate that represents a method you write to check if a condition is true or false. So your predicate method will take in one parameter, evaluate it, and then return a true or false. Let's see what this might look like:
// Your predicate function.
private bool FindRod(Person person)
{
    if (person.FirstName == "Rod")
        return true;
    return false;
}

// ...

Person foundPerson = people.Find(FindRod);
Now when you call the Find method, just pass in the name of your predicate method. The Find method will loop through all the items in the collection and run your predicate method until a true is returned.

Now that you have the basics down, I think you can take a look at the other Find methods and be able to tell what they do.

More Info: MSDN: Predicate(T) Generic Delegate

Wednesday, April 23, 2008

Delegates

The word "delegate" means "to represent another". A delegate in .NET is just another type, like class or string is a type. A delegate "represents another" method. I'll give examples of using a delegate next to a class so you can see some similarities in how they are used.

Declaring
// 1. Declare it.
public delegate int PerformCalculation(int x, int y);
public class Person
{
    public string GetName()
    {
        return "Mark";
    }
}
So it is like declaring any other type except instead of a variable name, you will be using a method signature. The method name (PerformCalculation) is how you reference the delegate.
You declare the variable "PerformCalculation" as the type "delegate". Think of it as defining a method signature (just like you would in an interface) and then putting the word "delegate" in front of it.

Assigning a Value
public void CreateAndUse()
{
    // 2. Assign a value.
    PerformCalculation calc = AddNumbers;
    Person person = new Person();
}

public int AddNumbers(int number1, int number2)
{
    return number1 + number2;
}
See how methods, like AddNumbers, are treated just like objects here? I assign it to my PerformCalculation delegate type. Make sure the signatures are similar.

Using It
// 3. Use it.
int sum = calc(1, 2);
string name = person.GetName();
Remember, your delegate is used to "represent another" method. So when you go to use it, you use it (call it) like a method.

Passing It
Like any object, you can pass it into methods or return it from methods. Here is an example of passing it into a method:
// 4. Pass it.
calc = SubtractNumbers;
string result = CalculateFreeSpace(calc, person);

//...

private int SubtractNumbers(int number1, int number2)
{
    return number1 - number2;
}

private string CalculateFreeSpace(PerformCalculation calc, Person person)
{
    int maxLength = 50;
    int freeSpace = calc(maxLength, person.GetName().Length);
    return string.Format("Free Space Left: {0}", freeSpace);
}
Before I passed as a parameter into the CalculateFreeSpace method, I decided to have it represent a different method with a similar signature.
Pretty interesting, huh? Here, I am injecting customized functionality into the method.
This opens up possibilities to you. You can use this as a way of doing your unit testing. Perhaps the delegate you pass in really calls a SQL Server. So before your unit test calls the method to be tested, you create your delegate to return a hard-coded result instead of calling your SQL Server.

I will be talking more about delegates tomorrow as well.

More Info: MSDN: Delegates

Tuesday, April 22, 2008

Formatting DateTime Strings

The DateTime object has some handy built in methods to format your date like .ToShortDateString() or .ToLongTimeString(). But often you need to combine two formats. Here are some ideas.
string format1 = string.Format("{0} {1}", DateTime.Now.ToShortDateString(), DateTime.Now.ToLongTimeString());
Here, I am just concatenating the output from two methods. There must be an easier way! To get the same exact output, you can customize the format of your ToString() output:
string format2 = DateTime.Now.ToString("M/dd/yyyy h:mm:ss tt");
You could also encapsulate this functionality into an extension method if you use it enough:
public static class DateTimeExtensions
{
    public static string ToShortDateLongTimeString(this DateTime d)
    {
        return d.ToString("M/dd/yyyy h:mm:ss tt");
    }
}
// ...
// To consume this extension method:
string format3 = DateTime.Now.ToShortDateLongTimeString();

More Info: MSDN: DateTime.ToString
More Info: List of ToString Formats

Monday, April 21, 2008

StartsWith, EndsWith

Here are a couple of useful methods that the string class provides. String.StartsWith and String.EndsWith.
List<string> names = new List<string>();
names.Add("Moeykens");
names.Add("Agee");
names.Add("Talbot");
names.Add("major");

foreach (string name in names)
{
    if (name.StartsWith("M", true, null))
        Console.WriteLine(name);
}

foreach (string name in names)
{
    if (name.EndsWith("e"))
        Console.WriteLine(name);
}
The first foreach loop will return:
Moeykens
major
The second parameter for the StartsWith method is set to "true" which tells the class to ignore case.

The second foreach will return:
Agee

More Info: MSDN: String.StartsWith
MSDN: String.EndsWith