For those that know a little bit about LINQ its understood that LINQ returns Enumerable<T> objects as the result of a LINQ query. And, many of you experiment with .NET 3.5 probably know is that LINQ supports projecting new, anonymous types. A project is where you end the query with select new {} and list the fields from the originating type to be in the result type. What may not be obvious is that you can add methods to projected anonymous types. In short, this means that you can add methods to dynamically created new types.
In the example I used LINQ and Visual Studio's object relational mapping capability with LINQ to SQL to create LQIN to SQL entity types for a Customer. Using a DataContext--also generated withe LINQ to SQL--a generic delegate Func<T,T> was defined that accepted two strings and concatenated the result. This generic delegate is then assigned to a named property in the projection of the select clause of the LINQ query. When the result set is iterated over and displayed the anonymous delegate is called like any other method (refer to Listing 1).
Listing 1: Define a generic delegate and assign it to a projection to add methods to projected anonymous types.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace LinqToSQLBlog
{
class Program
{
static void Main(string[] args)
{
CustomersAndOrdersDataContext context =
new CustomersAndOrdersDataContext();
context.Log = Console.Out;
Func<string, string, string> stringizer =
delegate(string title, string name){
const string mask = "{0}, {1}";
return string.Format(mask, name, title);
};
var customers = from customer in context.Customers
select new
{CompanyName=customer.CompanyName,
ContactName=customer.ContactName,
ContactTitle=customer.ContactTitle,
Address=customer.Address,
City=customer.City,
Region=customer.Region,
PostalCode=customer.PostalCode,
Phone=customer.Phone,
ToContact = stringizer
};
Array.ForEach(customers.ToArray(),
c=>Console.WriteLine(c.ToContact(c.ContactTitle, c.ContactName)));
Console.ReadLine();
}
}
}
By default when you create a projection the ToString method is provided to dump all of the properties of the new type. In the example ToContact was added to display a formatted output that displays the contact name and title. You can accomplish a similar result by adding an extension method and replacing ToContact in the Console.WriteLine call with the extension method (ToContact2) in the helper class. Listing 2 contains the definition of the extension method (and its class).
Listing 2: An extension method that will work with the anonymous projection too.
public static class Helper
{
public static string ToContact2<T>(this T table,
string title, string name)
{
const string mask = "{0}, {1}";
return string.Format(mask, name, title);
}
}
Really getting as many aspects of the .NET Framework is critical to becoming inventing with how you use the framework. Although all of the examples are short, the CodeDOM, generics, generic delegates, Lambda expressions (c=>Console.WriteLine...) and extension methods were all employed in crafting the solutions.
If you this post helped you add a comment. If you want more juicy tidbits like this one then check my blog or check out my book LINQ Unleashed for C# from Sams.