Gems of Themelia - Map and Template
Thursday, July 31, 2008
Themelia isn't a monolith. It couldn't be. Whatever major features it may have, those features have to be built from smaller pieces and those smaller pieces are reusable. You might call these caller pieces, the Gems of Themelia. They are the components that make the Themelia world go round, not just the Themelia web world either. These gems aren't even the Themelia.Web assembly, but are rather in the Themelia assembly ready for use in WPF, WCF, and console applications alike. There are many of them and I'll discuss a piece here and there in various documentation entries. In this entry: the Map and the Template.
At first glance, a Map looks like a regular .NET generic dictionary and in a sense, it is. In fact, the idea behind a map is that some data is mapped to other data, which is basically what a dictionary is. The thing that makes a Map a Map, however, is how the data is input and accessed.
A map comes in many varieties: the generic Map<T1, T2>, the Map, the StringObjectMap, among a few others. The generic Map contains GetKeyList and GetValueList methods, both of returns a .NET List object. The generic map also includes a PeekSafely method, which allows you to access data from the Map without having to check if it contains the key. If the key doesn't exist, the default of the type is returned. In addition to this method, there's also the Pull method, which returns the value of a mapped pair and completely removes it from the Map.
The non-generic Map types inherit from the generic Map. The most feature rich of these types is the type simply called Map. This type adds a series of helpful methods to aide in more efficient development and code reading. Besides having a AddMapEntrySeries, which allows quick addition of many MapEntry types, Map has a number of methods that accept what's called a Map pair, which is a string with the pattern "key=value". Using the AddPair and AddPairSeries methods, you can add multiple values like this: map.AddPairSeries("FirstName=John", "LastName="Doe"), which, by the way, is the same signature as the constructor. Here are some Map examples:
Map map = new Map("FirstName=John", "LastName=Doe"); //+ add single pair, pair series, and query string map.AddPair("UserName=JohnDoe"); map.AddPairSeries("Email=johndoe@tempuri.org", "WebSite=www.tempuri.org"); map.AddQueryString("SpouseName=Jane Doe&Birthdate=04/14/1974");
The Map is used all over Themelia and Themelia-based web sites. For example, a PayPal callback sends a query string-like, not in the URL, but in the content stream. Using a map (as well as the Themelia.Web.HttpData class), we can do this:
String data = Themelia.Web.HttpData.InputContentString; Map map = new Map(data.Split('&')); String paypalId = map.Pull("payer_id");
In addition to this, you can could also create a Map with whatever data you wanted, then databind that data to a WPF ListView, a ASP.NET DropDownList, or whatever by the GetMapEntryList( ) method, which provides a List of MapEntry elements, allowing for binding to a Key and Value property.
Another Themelia type that's used regularly is called the Template. This type makes code a lot easier to read. You can setup a template to accept a number of parameters, you can call a template's Interopolate method to create a string based upon that template using the information from a map. Given the previously shown example of a Map accepting a pair, a pair series, and query string, the following shows how the template can quickly quick very readable strings:
//+ template with pattern String pattern = "My name is {FirstName} {LastName}; {Email}; {WebSite}; {UserName}; {SpouseName}; {Birthdate}"; Template person = new Template(pattern); //+ Interpolate with data with string Console.WriteLine(person.Interpolate(map));
This example uses replaces the appropriate sections in the template with the actually data in the map. Compare that to the following:
Console.WriteLine(String.Format("My name is {0} {1}; {2}; {3}; {4}; {5}; {6}", firstName, LastName, email, webSite, UserName, spouseName, birthdate));
The template code is obviously more readable and manageable. Furthermore, by using this, you can set up a base set of templates and just pass Maps around to create strings in a centralized manner. Obviously, template patterns could easily be put into resources files too.
This isn't the end of the story with the Map as it will show up time and time again as it saves the day in many circumstances. For more information, please see the intellisense documentation provided in Themelia.




