<?xml version='1.0' encoding='UTF-8'?><rss xmlns:atom='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' version='2.0'><channel><atom:id>tag:blogger.com,1999:blog-5923247</atom:id><lastBuildDate>Fri, 27 Nov 2009 12:35:08 +0000</lastBuildDate><title>life in the so called space age</title><description>a blog by steve j rodgers</description><link>http://steverodgers.blogspot.com/</link><managingEditor>noreply@blogger.com (Steve J Rodgers)</managingEditor><generator>Blogger</generator><openSearch:totalResults>158</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-5923247.post-603194546005832405</guid><pubDate>Sat, 21 Mar 2009 16:41:00 +0000</pubDate><atom:updated>2009-03-22T02:41:50.852+10:00</atom:updated><title>Currying The ASP.NET Cache</title><description>&lt;p&gt;I’m reposting this blog entry with code in lieu of images after &lt;a href="http://www.interact-sw.co.uk/iangblog/"&gt;Ian&lt;/a&gt; sent me a rant email quite rightly complaining that he couldn’t read the code in the images (apologies to Ian and anyone else who reads this blog!)&lt;/p&gt;  &lt;p&gt;&amp;lt;snip/&amp;gt;&lt;/p&gt;  &lt;p&gt;The ASP.NET cache is a thing of beauty. But one thing that fills me with dread whenever I see it is an application littered with ASP.NET caching access code.    &lt;br /&gt;One of the other issues that developers have to handle is the possibility that stuff you put in it may not be there next time you ask for it back because the cache is prone to being purged when memory is constrained. This can lead to hideous looking developer code like this:&lt;/p&gt;  &lt;p&gt;public void Page_Load(object sender, EventArgs args)    &lt;br /&gt;{     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Person p = (Person)Cache[&amp;quot;human&amp;quot;]; &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (p == null)    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; p = HumanBusinessLogic.GetPerson(Request[&amp;quot;id&amp;quot;]);     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Cache[&amp;quot;human&amp;quot;] = p;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // go ahead and use p     &lt;br /&gt;}&lt;/p&gt;  &lt;p&gt;Yuck!!    &lt;br /&gt;To clean up the mess with a little refactoring, we could at least put the cache code in the business logic:&lt;/p&gt;  &lt;p&gt;public static Person GetPerson(string id)    &lt;br /&gt;{     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Cache cache = HttpContext.Current.Cache; &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Person p = (Person)cache[&amp;quot;human&amp;quot;]; &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (p == null)    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; p = HumanDataAccess.GetPerson(id);     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; cache[&amp;quot;human&amp;quot;] = p;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; } &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return p;    &lt;br /&gt;}&lt;/p&gt;  &lt;p&gt;But the problem now comes that for every business method that uses caching, there will be a cut and paste of the exact same code plus marginal refactor. The solution to that issue might lead us to develop a base class that offers up some kind of caching method that all business logic classes can then derive from and gain benefit.    &lt;br /&gt;This base class method would need to solve a couple of scenarios for it to be of any use to a derived class. First, it must look in the cache to see if the item is there and return it if it is. Second, it should have a mechanism of getting the item from the database and repopulating the cache if the item is not in the cache. The first scenario is a breeze, but the second scenario could be problematic. For example, most business logic entities come from a data access method invocation, but how many parameters will the data access method need and what types will they be? &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;A first crack at solving the problem might be to pretend that the data access method takes no parameters. That way, we could pass a delegate as a parameter that is invoked by the cache code when it detects a cache miss. The code would look like this (and notice the delegate takes no parameters)&lt;/p&gt;  &lt;p&gt;public delegate DataTable RetrieveData(); &lt;/p&gt;  &lt;p&gt;public class CurriedCache   &lt;br /&gt;{    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public static DataTable getCachedDataItem(string cacheKey,    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; RetrieveData retriever)    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Cache cache = HttpRuntime.Cache;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; DataTable item = (DataTable)cache[cacheKey];    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (item == null)    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; lock (typeof(CurriedCache))    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; item = (DataTable)cache[cacheKey];    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (item == null)    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; item = retriever();    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; cache.Add(cacheKey,    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; item,    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; null,    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Cache.NoAbsoluteExpiration,    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Cache.NoSlidingExpiration,    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; CacheItemPriority.Default,    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; null);    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; } &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return item;   &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }    &lt;br /&gt;}&lt;/p&gt;  &lt;p&gt;There are some huge issues with this implementation. First of all, it is assumed that the item being stored is a DataTable. Second, there is still the assumption that the retriever function takes no parameters. &lt;/p&gt;  &lt;p&gt;To solve the first problem, we can use generics:&lt;/p&gt;  &lt;p&gt;public delegate TResult RetrieveData&amp;lt;TResult&amp;gt;(); &lt;/p&gt;  &lt;p&gt;public class CurriedCache   &lt;br /&gt;{    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public static TResult getCachedDataItem&amp;lt;TResult&amp;gt;(    &lt;br /&gt;string cacheKey,    &lt;br /&gt;RetrieveData&amp;lt;TResult&amp;gt; retriever)    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; where TResult : class    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Cache cache = HttpRuntime.Cache;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; TResult item = (TResult)cache[cacheKey];    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (item == null)    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; lock (typeof(CurriedCache))    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; item = (TResult)cache[cacheKey];    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (item == null)    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; item = retriever();    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; cache.Add(cacheKey,    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; item,    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; null,    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Cache.NoAbsoluteExpiration,    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Cache.NoSlidingExpiration,    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; CacheItemPriority.Default,    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; null);    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; } &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return item;   &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }    &lt;br /&gt;}&lt;/p&gt;  &lt;p&gt;A useful bit of tidy up would be to replace the RetrieveData delegate with the Func&amp;lt;TResult&amp;gt; delegate that Microsoft already define as part of a family of delegates called Func that take no arguments, one argument, two arguments, etc respectively.&lt;/p&gt;  &lt;p&gt;namespace System   &lt;br /&gt;{    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public delegate TResult Func&amp;lt;TResult&amp;gt;();    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public delegate TResult Func&amp;lt;T, TResult&amp;gt;(T arg);    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public delegate TResult Func&amp;lt;T, TResult&amp;gt;(T arg);    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public delegate TResult Func&amp;lt;T1, T2, TResult&amp;gt;(T1 arg1,     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; T2 arg2);    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public delegate TResult Func&amp;lt;T1, T2, T3, TResult&amp;gt;(T1 arg1,     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; T2 arg2, T3 arg3);    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public delegate TResult Func&amp;lt;T1, T2, T3, T4, TResult&amp;gt;(T1 arg1, T2 arg2, T3 arg3, T4 arg4);    &lt;br /&gt;}&lt;/p&gt;  &lt;p&gt;It’s almost done, but not quite. There is still the serious limitation of the retriever function taking no parameters. The solution involves a bit of &lt;a href="http://en.wikipedia.org/wiki/Currying"&gt;currying&lt;/a&gt;. We will also define overloaded versions of the getCachedDataItem to cater for retriever functions that expect more than one parameter:&lt;/p&gt;  &lt;p&gt;public class CurriedCache   &lt;br /&gt;{    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public static TResult getCachedDataItem&amp;lt;TResult&amp;gt;(    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; string cacheKey,    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; object monitor,    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; DateTime absoluteExpiration,    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; TimeSpan slidingExpiration,    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Func&amp;lt;TResult&amp;gt; retriever)    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; where TResult : class    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Cache cache = HttpRuntime.Cache;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; TResult item = (TResult)cache[cacheKey];    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (item == null)    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; lock (monitor)    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; item = (TResult)cache[cacheKey];    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (item == null)    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; item = retriever();    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; cache.Add(cacheKey,    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; item,    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; null,    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; absoluteExpiration,    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; slidingExpiration,    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; CacheItemPriority.Default,    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; null);    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; } &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return item;   &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; } &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; public static TResult getCachedDataItem&amp;lt;T1, TResult&amp;gt;(   &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; string cacheKey,    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; object monitor,    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; DateTime absoluteExpiration,    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; TimeSpan slidingExpiration,    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Func&amp;lt;T1, TResult&amp;gt; retriever,    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; T1 a)    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; where TResult : class    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return getCachedDataItem&amp;lt;TResult&amp;gt;(cacheKey,    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; monitor,    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; absoluteExpiration,    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; slidingExpiration,    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; () =&amp;gt; { return retriever(a); });    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; } &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; public static TResult getCachedDataItem&amp;lt;T1, T2, TResult&amp;gt;(   &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; string cacheKey,    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; object monitor,    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; DateTime absoluteExpiration,    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; TimeSpan slidingExpiration,    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Func&amp;lt;T1, T2, TResult&amp;gt; retriever,    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; T1 a,    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; T2 b)    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; where TResult : class    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return getCachedDataItem&amp;lt;TResult&amp;gt;(cacheKey,    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; monitor,    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; absoluteExpiration,    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; slidingExpiration,    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; () =&amp;gt; { return retriever(a, b); });    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }    &lt;br /&gt;}&lt;/p&gt;  &lt;p&gt;Notice how the overloaded versions expect the retriever function to be a delegate that takes one or more arguments and notice how this delegate is then invoked in a wrapped delegate of the first type (Func&amp;lt;TResult&amp;gt;)    &lt;br /&gt;Since it’s likely we want to be able to lock cached items independently, it probably makes sense to introduce a lock parameter for finer grained locking. The addition of absolute and sliding expiration parameters also give a degree of finer control over caching behavior. The final tidy up also uses lamda expression syntax to invoke the delegates.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5923247-603194546005832405?l=steverodgers.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://steverodgers.blogspot.com/2009/03/currying-aspnet-cache_22.html</link><author>noreply@blogger.com (Steve J Rodgers)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-5923247.post-6545767771143285368</guid><pubDate>Wed, 18 Feb 2009 21:16:00 +0000</pubDate><atom:updated>2009-02-19T08:37:10.923+10:00</atom:updated><title>How to actively highlight a GridView row with JQuery</title><description>In a project, recently, I wanted to switch over to using the CSS Friendly Control Adapters to get the GridView to render its TR’s and TD’s with a CSS class so that all the styling could be dropped into a style sheet. The reason for doing this was because we wanted to highlight the row underneath the mouse by leveraging JQuery magic, thus improving the end user experience when there are many rows (See image below)&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_QWj4aaPgfRI/SZyHk7sITmI/AAAAAAAAAN8/lKuUXf-amNo/s1600-h/JQueryGridViewHighlightRow.jpg"&gt;&lt;img style="cursor: pointer; width: 320px; height: 240px;" src="http://2.bp.blogspot.com/_QWj4aaPgfRI/SZyHk7sITmI/AAAAAAAAAN8/lKuUXf-amNo/s320/JQueryGridViewHighlightRow.jpg" alt="" id="BLOGGER_PHOTO_ID_5304263529703427682" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The problem with the CSS Friendly Control Adapters is the all or nothing behaviour. Once you activate them in your project, they have global effect. I went looking for a mechanism that would allow me to turn off the effect on a per GridView basis and was initially excited to see the GridView attribute AdapterEnabled="false"...but after a short test, it became apparent that it doesn’t work!&lt;br /&gt;&lt;br /&gt;So, I decided to dump the CSS Friendly Control Adapters and go for a home grown route instead.&lt;br /&gt;&lt;br /&gt;The first thing to do is to *remove* &amp;lt;RowStyle&amp;gt; and &amp;lt;AlternatingRowStyle&amp;gt; elements in the GridView and add a CssClass=”selectableGridView” (see image below):&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_QWj4aaPgfRI/SZyNVkIeuEI/AAAAAAAAAOk/DGPgdnEnzm4/s1600-h/GridCode.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 320px; height: 240px;" src="http://3.bp.blogspot.com/_QWj4aaPgfRI/SZyNVkIeuEI/AAAAAAAAAOk/DGPgdnEnzm4/s320/GridCode.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5304269862751615042" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;If you fail to remove these elements, they produce HTML as seen below (see how the element gets translated into a style='....' in the HTML)&lt;br /&gt;&lt;br /&gt;....and don't forget to add the CssClass=”selectableGridView” to the GridView (as marked in the green square)&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_QWj4aaPgfRI/SZyJHYKpqfI/AAAAAAAAAOM/FJjPzFWYIBI/s1600-h/CrapGridViewStyles.jpg"&gt;&lt;img style="cursor: pointer; width: 320px; height: 240px;" src="http://1.bp.blogspot.com/_QWj4aaPgfRI/SZyJHYKpqfI/AAAAAAAAAOM/FJjPzFWYIBI/s320/CrapGridViewStyles.jpg" alt="" id="BLOGGER_PHOTO_ID_5304265220974815730" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The reason for removing them is because we’re going to be using JQuery to add a class dynamically to the row when the mouse is over it and this will have no effect whatsoever if the local styling is left in place. By the way, there's another bonus for doing this and that's to reduce the size of the page which will therefore increase page load time.&lt;br /&gt;&lt;br /&gt;So, the JQuery code looks like this:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_QWj4aaPgfRI/SZyJmwNbdtI/AAAAAAAAAOU/rnN__3ph0Wc/s1600-h/GridViewJQuery.jpg"&gt;&lt;img style="cursor: pointer; width: 320px; height: 172px;" src="http://1.bp.blogspot.com/_QWj4aaPgfRI/SZyJmwNbdtI/AAAAAAAAAOU/rnN__3ph0Wc/s320/GridViewJQuery.jpg" alt="" id="BLOGGER_PHOTO_ID_5304265760004863698" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The JQuery code has two jobs it must do. First, it needs to put back the row style and alternating row style. This is done with the following code:&lt;br /&gt;&lt;br /&gt;$('.selectableGridView tr:odd').not(':has(th)').addClass('SelectableGridViewAlternateRow');&lt;br /&gt;&lt;br /&gt;$('.selectableGridView tr:even').not(':has(th)').addClass('SelectableGridViewRow');&lt;br /&gt;&lt;br /&gt;The first line applies the alternating row style via the class .SelectableGridViewAlternateRow and the second line applies the normal non alternating row style via the class .SelectableGridViewRow. We need to be careful not to include the rows that are in the table header, hence the .not(':has(th)') selector to filter those guys out.&lt;br /&gt;&lt;br /&gt;The next piece of JQuery magic is to highlight the row underneath the mouse.&lt;br /&gt;&lt;br /&gt;$('.selectableGridView tr').not(':has(th)').mouseover(function() {&lt;br /&gt;&lt;br /&gt;$(this).addClass('SelectableGridViewHighlightRow');}).mouseout(function()&lt;br /&gt;$(this).removeClass('SelectableGridViewHighlightRow');});&lt;br /&gt;&lt;br /&gt;Again, we simply filter out the rows in the header and then apply the .SelectableGridViewHighlightRow class in mouseover and then remove it in mouseout.&lt;br /&gt;&lt;br /&gt;To finish up, the style sheet sets up the rules needed to bring it all together&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_QWj4aaPgfRI/SZyKA-2BsTI/AAAAAAAAAOc/yK6hT1CSUdo/s1600-h/GridViewStyleSheet.jpg"&gt;&lt;img style="cursor: pointer; width: 320px; height: 151px;" src="http://3.bp.blogspot.com/_QWj4aaPgfRI/SZyKA-2BsTI/AAAAAAAAAOc/yK6hT1CSUdo/s320/GridViewStyleSheet.jpg" alt="" id="BLOGGER_PHOTO_ID_5304266210609836338" border="0" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5923247-6545767771143285368?l=steverodgers.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://steverodgers.blogspot.com/2009/02/how-to-actively-highlight-gridview-row.html</link><author>noreply@blogger.com (Steve J Rodgers)</author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_QWj4aaPgfRI/SZyHk7sITmI/AAAAAAAAAN8/lKuUXf-amNo/s72-c/JQueryGridViewHighlightRow.jpg' height='72' width='72'/><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-5923247.post-5287851672389969329</guid><pubDate>Sat, 27 Dec 2008 19:57:00 +0000</pubDate><atom:updated>2008-12-29T07:44:55.719+10:00</atom:updated><title>understanding C#'s yield return statement</title><description>The C# yield return statement causes the C# compiler to generate a fair amount of additional IL instructions. This generated code can easily be seen with a tool like Reflector. Although, understanding exactly how the generated code works is not especially easy from first glance since it is rather verbose and somewhat lacking in useful variable names.&lt;br /&gt;&lt;br /&gt;A first port of call might be to extract the generated code with Reflector into a Visual Studio .NET C# source file. Sadly, an attempt at compilation will result in errors :( It turns out that the generated IL code does some things that ordinary C# programs are forbidden to do.&lt;br /&gt;&lt;br /&gt;Specifically, the iterator syntax magic creates an implementation of IEnumerator&lt;t&gt;.MoveNext() that can be called multiple times, with each call returning to the same point it was at previously, prior to returning last time round. So how does it do that? How can you call a method multiple times and each time have it resume from the exact same point it left previously?&lt;br /&gt;&lt;br /&gt;To see this programming style in action, one approach might be to write a simple program from scratch that demonstrates how you could mimic the behaviour of calling a method multiple times and returning to the same point you previously left off. C# is not going to be the right language choice since it forbids the very programming style we want to emulate! It turns out that a simple C++ program is a good candidate for demonstrating the concept and has the benefits of being compilable and therefore debuggable and also reasonably easy to understand.&lt;br /&gt;&lt;br /&gt;As an example, consider the following C++ program that displays the first 6 prime numbers with a function GetPrime() that when called each time will return the next prime number in the array.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_QWj4aaPgfRI/SVaJNpCCiSI/AAAAAAAAAL4/yFkKD89-6Gw/s1600-h/iterator_code_a.jpg"&gt;&lt;img style="cursor: pointer; width: 253px; height: 400px;" src="http://1.bp.blogspot.com/_QWj4aaPgfRI/SVaJNpCCiSI/AAAAAAAAAL4/yFkKD89-6Gw/s400/iterator_code_a.jpg" alt="" id="BLOGGER_PHOTO_ID_5284562080211568930" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;For simplicity, the program uses several global variables but it’s not hard to imagine these being hoisted into a class as member variables with the GetPrime() function elevated to method status.&lt;br /&gt;&lt;br /&gt;The program begins life by calling GetPrime() for the first time. At this time, the global variable called ‘state’ has a value of zero, so the code enters the while loop and extracts the first prime number from the array and sets the global variable ‘state’ to 2 before returning the prime number from the function. The next call into GetPrime(), we note that ‘state’ has a value of 2, so it will trigger the case that causes the code to jump back into the middle of the while loop (effectively jumping back to the exact position where it left last time had it not returned from the function) with goto getAnotherPrime and so the code loops round to extract the next prime number from the array and returns it to the caller. When the global variable ‘count’ is no longer less that the number of primes in the array, the while loop in GetPrime() will drop out and cause the function to return zero, thus causing the while loop in _tmain() to terminate.&lt;br /&gt;&lt;br /&gt;The naughty part of the code from a C# perspective is the goto label (getAnotherPrime) appearing after a return statement, something the C# compiler considers to be unreachable code (which seems quite reasonable).&lt;br /&gt;&lt;br /&gt;So the secret of the technique is to maintain a state machine in memory of where the code is at in the loop. If ‘state’ is 2, then it means the next call to GetPrime() should re-enter the loop at the place it last left off (that place being just after the return statement). If 'state' is 0, then this is the very first call into the function and iteration is commencing. When 'state' has the value 1, it doesn't stay that way for long since the code will loop back round and soon become 2 again. The assignment of value 1 into 'state' doesn't have much effect other than keeping the compiler happy such that the label actually serves a purpose.&lt;br /&gt;&lt;br /&gt;If you understand the above code then it should now be reasonably trivial for the reader to decompile the following C# program with Reflector and see how it uses this exact same state machine technique in IEnumerator&lt;t&gt;.MoveNext():&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_QWj4aaPgfRI/SVaJdr0Lo3I/AAAAAAAAAMA/H4FqawzcLvk/s1600-h/iterator_code_b.jpg"&gt;&lt;img style="cursor: pointer; width: 400px; height: 281px;" src="http://2.bp.blogspot.com/_QWj4aaPgfRI/SVaJdr0Lo3I/AAAAAAAAAMA/H4FqawzcLvk/s400/iterator_code_b.jpg" alt="" id="BLOGGER_PHOTO_ID_5284562355836658546" border="0" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5923247-5287851672389969329?l=steverodgers.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://steverodgers.blogspot.com/2008/12/understanding-cs-yield-return-statement.html</link><author>noreply@blogger.com (Steve J Rodgers)</author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_QWj4aaPgfRI/SVaJNpCCiSI/AAAAAAAAAL4/yFkKD89-6Gw/s72-c/iterator_code_a.jpg' height='72' width='72'/><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>1</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-5923247.post-5844001778948117899</guid><pubDate>Sat, 01 Nov 2008 14:23:00 +0000</pubDate><atom:updated>2008-11-02T01:13:10.524+10:00</atom:updated><title>Cloud Computing</title><description>I did not attend PDC this year so I'm blogging on the back of having streamed the Ray Ozzie keynote.&lt;br /&gt;&lt;br /&gt;I feel sure I won't be the only person to wonder whether Cloud computing is likely to be a huge success for Microsoft. In theory, it makes a lot of sense, but in practice, I can't help wondering whether this is to a large extent another 'Hailstorm'-esque Microsoft dream. Will companies really be queuing up to have Microsoft data centres host their application code and corporate data? However wonderful the platform may turn out to be, what does it mean to pass responsibility for the safe keeping of your data with a third party like Microsoft?&lt;br /&gt;&lt;br /&gt;Why do we need Cloud computing anyway? What does it do such that we cannot live without it? I mean, if we look at .NET and ask the same question, the answer seems obvious - we could not live without it and thank goodness the COM era came to an end. Anyone who uses a computer in the modern world reaps benefit from the technological innovation of .NET - will the same be true of a Microsoft cloud?&lt;br /&gt;&lt;br /&gt;Well, I guess the cloud could provide unlimited scalability with that kind of horsepower packed into the huge data centre. But I wonder how many companies will actually need that kind of scalability? And doesn't scalability really boil down to writing code that can be scaled in the first place as opposed to taking any old bit of code and throwing more cores at it? I'm thinking of plentyoffish.com when I say this - one smart guy (Markus Frind), 2 databases, one web server and thousands of hits per day with a truly scalable piece of software. I'm pretty sure he doesn't need the cloud and I'm pretty sure he gets more hits than most companies who will sign up for the cloud.&lt;br /&gt;&lt;br /&gt;Failover also has to be a consideration in any scalable application, but do we not already have web server farms and SQL Server clusters that keep the ecosphere of Microsoft applications more than available?&lt;br /&gt;&lt;br /&gt;To a large extent, I think it's going to boil down to price. If Microsoft can host your code and data in their cloud at a significantly reduced cost to your business than you hosting it, then perhaps they're onto a winner. But even if they do manage to make the cloud financially competitive, the question still remains as to whether you trust Microsoft to be the caretakers of your company's greatest assets.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5923247-5844001778948117899?l=steverodgers.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://steverodgers.blogspot.com/2008/11/cloud-computing.html</link><author>noreply@blogger.com (Steve J Rodgers)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-5923247.post-3959718189654979880</guid><pubDate>Fri, 30 May 2008 08:50:00 +0000</pubDate><atom:updated>2008-05-30T19:01:30.701+10:00</atom:updated><title>JSONized query strings</title><description>&lt;span style="font-family:verdana;"&gt;I often have to Response.Redirect to an ASP.NET page that takes a lot of parameters. There are a few ways of doing this. One way might be to invoke the page with a query string that contains the parameters: &lt;/span&gt;&lt;br /&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;span style="font-family:verdana;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family:verdana;"&gt;Foo.aspx?a=66&amp;amp;b=77 &lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;span style="font-family:verdana;"&gt;If you think of the query string parameters as bunch of properties on a class then you could easily see how one might author that class to also serialize and deserialize the query string by leveraging StringBuilder.Append or String.Format and String.Split etc etc.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family:Verdana;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family:Verdana;"&gt;&lt;br /&gt;&lt;/span&gt; &lt;/div&gt;&lt;div&gt;&lt;span style="font-family:Verdana;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family:Verdana;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family:verdana;"&gt;I’ve been working with Microsoft AJAX recently and I'd used the text based JSON serializer a couple of times and it got me thinking about how I might leverage that to serialize my object properties to and from the query string. [The XmlSerializer might seem like another approach, but ASP.NET really doesn’t like angle brackets (even encoded) sent as data in the query string – it barfs in case you were wondering with a ‘that data looks very suspicious’ type message.] &lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;span style="font-family:verdana;"&gt;So I decided to give the JSON parser a whirl and it works like a charm. Here’s what my JSON encoded query string looks like: &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family:verdana;"&gt;Foo.aspx?qps={"A":66,"B":77} &lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;span style="font-family:verdana;"&gt;Here's the class: &lt;/span&gt;&lt;a href="http://1.bp.blogspot.com/_QWj4aaPgfRI/SD--BO2P9fI/AAAAAAAAAHg/m-plt251fds/s1600-h/theclass.JPG"&gt;&lt;/a&gt;&lt;/div&gt;&lt;a href="http://2.bp.blogspot.com/_QWj4aaPgfRI/SD_AVe2P9iI/AAAAAAAAAH4/i4h5bLl-UDw/s1600-h/theclass.JPG"&gt;&lt;img id="BLOGGER_PHOTO_ID_5206091169553970722" style="CURSOR: hand" alt="" src="http://2.bp.blogspot.com/_QWj4aaPgfRI/SD_AVe2P9iI/AAAAAAAAAH4/i4h5bLl-UDw/s400/theclass.JPG" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;span style="font-family:verdana;"&gt;Here's the caller: &lt;/span&gt;&lt;a href="http://2.bp.blogspot.com/_QWj4aaPgfRI/SD--Re2P9gI/AAAAAAAAAHo/_TLGLOUOGag/s1600-h/caller.JPG"&gt;&lt;/a&gt;&lt;/div&gt;&lt;a href="http://4.bp.blogspot.com/_QWj4aaPgfRI/SD_Ah-2P9jI/AAAAAAAAAIA/dIVpZiTQ4FQ/s1600-h/caller.JPG"&gt;&lt;img id="BLOGGER_PHOTO_ID_5206091384302335538" style="CURSOR: hand" alt="" src="http://4.bp.blogspot.com/_QWj4aaPgfRI/SD_Ah-2P9jI/AAAAAAAAAIA/dIVpZiTQ4FQ/s400/caller.JPG" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;span style="font-family:verdana;"&gt;Here's the callee: &lt;/span&gt;&lt;a href="http://2.bp.blogspot.com/_QWj4aaPgfRI/SD--ee2P9hI/AAAAAAAAAHw/aVdzkd3VGoY/s1600-h/callee.JPG"&gt;&lt;/a&gt;&lt;/div&gt;&lt;a href="http://1.bp.blogspot.com/_QWj4aaPgfRI/SD_AnO2P9kI/AAAAAAAAAII/QXFArdiOKQI/s1600-h/callee.JPG"&gt;&lt;img id="BLOGGER_PHOTO_ID_5206091474496648770" style="CURSOR: hand" alt="" src="http://1.bp.blogspot.com/_QWj4aaPgfRI/SD_AnO2P9kI/AAAAAAAAAII/QXFArdiOKQI/s400/callee.JPG" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;span style="font-family:verdana;"&gt;I *always* wrap the FromJSON call in a try / catch block in case someone tries to send a hacked query string that clearly won’t deserialize. &lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5923247-3959718189654979880?l=steverodgers.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://steverodgers.blogspot.com/2008/05/jsonized-query-strings.html</link><author>noreply@blogger.com (Steve J Rodgers)</author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_QWj4aaPgfRI/SD_AVe2P9iI/AAAAAAAAAH4/i4h5bLl-UDw/s72-c/theclass.JPG' height='72' width='72'/><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-5923247.post-6276415846224646084</guid><pubDate>Sun, 04 May 2008 21:48:00 +0000</pubDate><atom:updated>2008-05-05T09:35:16.395+10:00</atom:updated><title>Creating 'Expression Blend' ScrollBars in WPF</title><description>&lt;span style="font-family:verdana;"&gt;The scroll bars in Expression Blend are very nice. Nice enough that I thought I’d spend some time this afternoon figuring out how I could modify the WPF scroll bar control template. Fortunately, it turned out that there really wasn’t that much work involved. Here’s the result:&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;a href="http://3.bp.blogspot.com/_QWj4aaPgfRI/SB5Cn7g3rOI/AAAAAAAAAGk/v6zwGyycmcA/s1600-h/BlendScrollBar.jpg"&gt;&lt;span style="font-family:verdana;"&gt;&lt;img id="BLOGGER_PHOTO_ID_5196664273790020834" style="CURSOR: hand" alt="" src="http://3.bp.blogspot.com/_QWj4aaPgfRI/SB5Cn7g3rOI/AAAAAAAAAGk/v6zwGyycmcA/s400/BlendScrollBar.jpg" border="0" /&gt;&lt;/span&gt;&lt;/a&gt;&lt;span style="font-family:verdana;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;I started off by grabbing the template from &lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/ms742173.aspx"&gt;&lt;span style="font-family:verdana;"&gt;MSDN&lt;/span&gt;&lt;/a&gt;&lt;span style="font-family:verdana;"&gt;. The scroll bar template consists of a style that brings into play either the VerticalScrollBar template or the HorizontalScrollBar template via the Orientation dependency property as seen: &lt;/span&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/_QWj4aaPgfRI/SB5CaLg3rNI/AAAAAAAAAGc/NjHA1D38U7I/s1600-h/rootTemplate.jpg"&gt;&lt;span style="font-family:verdana;"&gt;&lt;img id="BLOGGER_PHOTO_ID_5196664037566819538" style="CURSOR: hand" alt="" src="http://4.bp.blogspot.com/_QWj4aaPgfRI/SB5CaLg3rNI/AAAAAAAAAGc/NjHA1D38U7I/s400/rootTemplate.jpg" border="0" /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;span style="font-family:verdana;"&gt;The remaining discussion will only focus on the VerticalScrollBar, since the solution is almost exactly the same for HorizontalScrollBar. &lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;span style="font-family:verdana;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family:verdana;"&gt;The RepeatButton defined in the VerticalScrollBar template seen at Grid="0" and again at Grid="2" defines the up arrow and down arrow respectively. I made these a little more elongated to mirror the Blend arrows by changing the content properties as follows: &lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;span style="font-family:verdana;"&gt;Top arrow: Content="M 0 8 L 8 8 L 4 0 Z" &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family:verdana;"&gt;Bottom arrow: Content="M 0 0 L 4 8 L 8 0 Z"&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;span style="font-family:verdana;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;a href="http://2.bp.blogspot.com/_QWj4aaPgfRI/SB5DZrg3rPI/AAAAAAAAAGs/aGtQiXrBIqc/s1600-h/VertTemplate.jpg"&gt;&lt;span style="font-family:verdana;"&gt;&lt;img id="BLOGGER_PHOTO_ID_5196665128488512754" style="CURSOR: hand" alt="" src="http://2.bp.blogspot.com/_QWj4aaPgfRI/SB5DZrg3rPI/AAAAAAAAAGs/aGtQiXrBIqc/s400/VertTemplate.jpg" border="0" /&gt;&lt;/span&gt;&lt;/a&gt;&lt;span style="font-family:verdana;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;div&gt;&lt;span style="font-family:verdana;"&gt;The scroll thumb also needed some attention. The shape of the thumb at both ends is more rounded than the default, so I increased the CornerRadius:&lt;br /&gt;CornerRadius="4"&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;span style="font-family:verdana;"&gt;Also, the thumb in blend has no border, so I removed the BorderBrush and set the:&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;span style="font-family:verdana;"&gt;BorderThickness="0"&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;Another difference is that the thumb is highlighted when the mouse is over it and changes colour to black while it is being dragged. Both of these are dependency properties that can be modified to the appropriate values with triggers:&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;span style="font-family:verdana;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;a href="http://1.bp.blogspot.com/_QWj4aaPgfRI/SB5EBbg3rQI/AAAAAAAAAG0/nHS3U5c_FrU/s1600-h/scrollthumb.jpg"&gt;&lt;span style="font-family:verdana;"&gt;&lt;img id="BLOGGER_PHOTO_ID_5196665811388312834" style="CURSOR: hand" alt="" src="http://1.bp.blogspot.com/_QWj4aaPgfRI/SB5EBbg3rQI/AAAAAAAAAG0/nHS3U5c_FrU/s400/scrollthumb.jpg" border="0" /&gt;&lt;/span&gt;&lt;/a&gt;&lt;span style="font-family:verdana;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;div&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;span style="font-family:verdana;"&gt;Notice that I had to give the Border a name ‘roundedBorder’ so that the triggers could reference it.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family:verdana;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;span style="font-family:verdana;"&gt;ScrollBarLineButton defines the style and template for the repeater button that houses the arrows (which will end up being up or down for vertical scroll bar. And left or right for a horizontal scroll bar). The template for ScrollBarLineButton acquires the visual for the arrow by databinding to the Content property of the template parent – a neat trick that means only one ScrollBarLineButton needs to be defined for the whole template to be able to deal with all four arrows.&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;span style="font-family:verdana;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;span style="font-family:verdana;"&gt;To get the ScrollBarLineButton to look like the blend version, I had to make a few more changes. The arrow is highlighted when the mouse is over it – in much the same way as the thumb. To achieve this, I gave the Path a name ‘glyph’ and then changed the trigger ‘IsMouseOver’ to retarget to ‘glyph’ Fill to the colour: GlyphMouseOver. The IsPressed trigger also needs to mirror the thumb and sets the ‘glyph’ Fill to black. &lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;span style="font-family:verdana;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;a href="http://4.bp.blogspot.com/_QWj4aaPgfRI/SB5E8Lg3rRI/AAAAAAAAAG8/vBx-i4eIvYY/s1600-h/scrollbarlinebutton.jpg"&gt;&lt;span style="font-family:verdana;"&gt;&lt;img id="BLOGGER_PHOTO_ID_5196666820705627410" style="CURSOR: hand" alt="" src="http://4.bp.blogspot.com/_QWj4aaPgfRI/SB5E8Lg3rRI/AAAAAAAAAG8/vBx-i4eIvYY/s400/scrollbarlinebutton.jpg" border="0" /&gt;&lt;/span&gt;&lt;/a&gt;&lt;span style="font-family:verdana;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;div&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;span style="font-family:verdana;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family:verdana;"&gt;Finally, I also had to change some of the brushes defined for the scrollbar. Here are the changed versions: &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family:verdana;"&gt;&amp;lt;SolidColorBrush x:Key="GlyphBrush"Color="#FF7E7C7C" /&amp;gt;&lt;br /&gt;&amp;lt;SolidColorBrush x:Key="GlyphMouseOver"Color="#FFE8E8E8"/&amp;gt;&lt;br /&gt;&amp;lt;SolidColorBrush x:Key="PressedBrush" Color="Black"/&amp;gt;&lt;br /&gt;&amp;lt;SolidColorBrush x:Key="NormalBrush"Color="#585858"/&amp;gt;&lt;br /&gt;&lt;/div&gt;&lt;/span&gt;&lt;solidcolorbrush key="GlyphBrush"&gt;&lt;div&gt;&lt;span style="font-family:verdana;"&gt;&lt;solidcolorbrush color="#FFE8E8E8" key="GlyphMouseOver"&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family:verdana;"&gt;&lt;solidcolorbrush color="Black" key="PressedBrush"&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family:verdana;"&gt;&lt;solidcolorbrush color="#FF7E7C7C" key="GlyphBrush"&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family:verdana;"&gt;&lt;solidcolorbrush color="#FFE8E8E8" key="GlyphMouseOver"&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family:verdana;"&gt;&lt;solidcolorbrush color="Black" key="PressedBrush"&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family:verdana;"&gt;&lt;solidcolorbrush color="#585858" key="NormalBrush"&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5923247-6276415846224646084?l=steverodgers.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://steverodgers.blogspot.com/2008/05/creating-expression-blend-scrollbars.html</link><author>noreply@blogger.com (Steve J Rodgers)</author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_QWj4aaPgfRI/SB5Cn7g3rOI/AAAAAAAAAGk/v6zwGyycmcA/s72-c/BlendScrollBar.jpg' height='72' width='72'/><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>7</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-5923247.post-3238156656528093864</guid><pubDate>Wed, 30 Jan 2008 18:12:00 +0000</pubDate><atom:updated>2008-01-31T06:04:21.509+10:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>WPF</category><title>WPF CoverFlow Clone</title><description>&lt;span style="font-family:verdana;"&gt;I recently decided to spend some time hacking up a CoverFlow clone in WPF. Of course, what I managed to achieve in the space of a day is nowhere near as good as the real CoverFlow application that Apple deploys but that's not the point! The point is, it amazes me how quickly and effortlessly I was able to do it with the power of WPF. It also amazes me how long something similar would have taken in any previous technology like Windows Forms or Win32!&lt;br /&gt;&lt;br /&gt;Here's what the 'final' XBAP version looks like: &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;p align="center"&gt;&lt;a href="http://4.bp.blogspot.com/_QWj4aaPgfRI/R6C_oIdVluI/AAAAAAAAAEk/OGglNtfJPdg/s1600-h/coverflowclone.jpg"&gt;&lt;span style="font-family:verdana;"&gt;&lt;img id="BLOGGER_PHOTO_ID_5161335869152794338" style="CURSOR: hand" alt="" src="http://4.bp.blogspot.com/_QWj4aaPgfRI/R6C_oIdVluI/AAAAAAAAAEk/OGglNtfJPdg/s400/coverflowclone.jpg" border="0" /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;My approach was to almost completely restyle a ListBox. The first step was to redefine the ControlTemplate of ListBoxItem to be a Grid of 1 row and 1 column containing a StackPanel which in turn contained both the ContentPresenter and a Rectangle. The rectangle is there to produce the reflected image of the ContentPresenter.&lt;br /&gt;&lt;br /&gt;Here's the XAML for doing that: &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/_QWj4aaPgfRI/R6DM0odVl1I/AAAAAAAAAFc/uHKdWVhNYOo/s1600-h/Reflection.jpg"&gt;&lt;span style="font-family:verdana;"&gt;&lt;img id="BLOGGER_PHOTO_ID_5161350377552320338" style="CURSOR: hand" alt="" src="http://2.bp.blogspot.com/_QWj4aaPgfRI/R6DM0odVl1I/AAAAAAAAAFc/uHKdWVhNYOo/s400/Reflection.jpg" border="0" /&gt;&lt;/span&gt;&lt;/a&gt;&lt;span style="font-family:verdana;"&gt;&lt;br /&gt;&lt;br /&gt;The VisualBrush used to paint the Rectangle has to be flipped in the Y-axis with a ScaleTransform and then put back into the correct position with the TranslateTransform. The TranslateTransform figures out how much to offset in the Y axis via databinding to the ActualHeight of the ContentPresenter. The OpacityMask applied to the Rectangle ensures that the reflection gradually dissolves away.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;The StackPanel that contains the ContentPresenter and Rectangle (reflected image) looks like this:&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;a href="http://3.bp.blogspot.com/_QWj4aaPgfRI/R6DQF4dVl2I/AAAAAAAAAFk/_4YKQ7DbrfQ/s1600-h/stack.jpg"&gt;&lt;span style="font-family:verdana;"&gt;&lt;img id="BLOGGER_PHOTO_ID_5161353972439947106" style="CURSOR: hand" alt="" src="http://3.bp.blogspot.com/_QWj4aaPgfRI/R6DQF4dVl2I/AAAAAAAAAFk/_4YKQ7DbrfQ/s400/stack.jpg" border="0" /&gt;&lt;/span&gt;&lt;/a&gt;&lt;span style="font-family:verdana;"&gt; &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;This has a couple of transforms that do nothing until they are animated later; a TranslateTransform and a ScaleTransform. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;When the ListBoxItem is selected, several animations run in parallel, effectively moving the StackPanel down in the Y axis by running the TranslateTransform while at the same time running a ScaleTransform which enlarges it in X and Y. The combined effect of these animations running in parallel is the sensation that the selected ListBoxItem springs forward towards the end user. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;The animations are initiated by EventTrigger's; one each for the routed events: ListBoxItem.Selected and ListBoxItem.Unselected. Here's the XAML for the animations in their respective EventTrigger's&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/_QWj4aaPgfRI/R6DURIdVl3I/AAAAAAAAAFs/URAhRHSM958/s1600-h/triggers.jpg"&gt;&lt;span style="font-family:verdana;"&gt;&lt;img id="BLOGGER_PHOTO_ID_5161358563759986546" style="CURSOR: hand" alt="" src="http://4.bp.blogspot.com/_QWj4aaPgfRI/R6DURIdVl3I/AAAAAAAAAFs/URAhRHSM958/s400/triggers.jpg" border="0" /&gt;&lt;/span&gt;&lt;/a&gt;&lt;span style="font-family:verdana;"&gt;&lt;br /&gt;&lt;br /&gt;When the ListBoxItem becomes Unselected, the Unselected EventTrigger ensures the StackPanel moves back into it's original position and size prior to being selected - effectively reversing the work done of the Selected EventTrigger.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5923247-3238156656528093864?l=steverodgers.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://steverodgers.blogspot.com/2008/01/wpf-coverflow-clone.html</link><author>noreply@blogger.com (Steve J Rodgers)</author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_QWj4aaPgfRI/R6C_oIdVluI/AAAAAAAAAEk/OGglNtfJPdg/s72-c/coverflowclone.jpg' height='72' width='72'/><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>2</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-5923247.post-2960621451998258314</guid><pubDate>Thu, 21 Jun 2007 03:48:00 +0000</pubDate><atom:updated>2007-06-21T13:58:45.408+10:00</atom:updated><title>Avoid CrpytoStream.Flush()</title><description>I needed to attend to some code that was violating an FxCop rule earlier. The code snippet looks something like this:&lt;br /&gt;&lt;br /&gt;using (CryptoStream cryptoStream = new CryptoStream(outputStream...))&lt;br /&gt;{&lt;br /&gt;cryptoStream.Write(data, 0, data.Length);&lt;br /&gt;cryptoStream.Close();&lt;br /&gt;encrypted = outputStream.ToArray();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;The FxCop rule being violated is that we are calling Close and yet Dispose will automatically be called because we are in the context of a using construct.&lt;br /&gt;&lt;br /&gt;So I figured I'd just call Flush() instead of Close() - so it would look like this:&lt;br /&gt;&lt;br /&gt;using (CryptoStream cryptoStream = new CryptoStream(outputStream...))&lt;br /&gt;{&lt;br /&gt;cryptoStream.Write(data, 0, data.Length);&lt;br /&gt;cryptoStream.Flush();&lt;br /&gt;encrypted = outputStream.ToArray();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;That turned out to be bad karma and barfed during unit testing with:&lt;br /&gt;System.Security.Cryptography.CryptographicException : Padding is invalid and cannot be removed&lt;br /&gt;&lt;br /&gt;I had a look at CrytoStream.Flush() with Reflector and it looks like this:&lt;br /&gt;&lt;br /&gt;public override void Flush()&lt;br /&gt;{&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;Hmmmm not much going on there seeing as the documentation says - &lt;br /&gt;"Clears all buffers for this stream and causes any buffered data to be written to the underlying device"&lt;br /&gt;&lt;br /&gt;So I checked out the CryptoStream.Dispose() and that makes a call to CryptoStream.FlushFinalBlock() prior to calling CryptoStream.Close(). So I have replaced our call to Flush() with FlushFinalBlock()...makes me wonder whether Flush() was an intentional override that does absolutely nothing whatsoever other than inhibit base class behavior....?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5923247-2960621451998258314?l=steverodgers.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://steverodgers.blogspot.com/2007/06/crpytostreamflush.html</link><author>noreply@blogger.com (Steve J Rodgers)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-5923247.post-7635797981043318662</guid><pubDate>Sat, 02 Jun 2007 11:15:00 +0000</pubDate><atom:updated>2007-06-02T21:37:23.390+10:00</atom:updated><title>Vista graphics card driver joys...</title><description>My primary machine is a DELL D820 and I'm running Vista RTM. I was thinking that not only the graphics seemed a bit sluggish but also Vista Performance tool (just go Start-&gt;Performance Information &amp; Tools) reported my Graphics rating as 2.3 out of 5.9 which aint so good. I checked out the installed driver and saw that it was a Microsoft generic driver so I surfed to the DELL website and had a quick look to see if there was a better driver. Sure enough, I found the Nvidia driver and installed it. After rebooting, I asked Performance Information &amp; Tools to update my score and it then came in at 3.6 and the UI is really, really zippy compared to what it was. &lt;br /&gt;&lt;br /&gt;So if you're running Vista and you're using the generic display driver, go find the non generic one and enjoy Vista even more :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5923247-7635797981043318662?l=steverodgers.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://steverodgers.blogspot.com/2007/06/vista-graphics-card-driver-joys.html</link><author>noreply@blogger.com (Steve J Rodgers)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>1</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-5923247.post-4768627268990667070</guid><pubDate>Thu, 31 May 2007 07:25:00 +0000</pubDate><atom:updated>2007-06-21T13:24:52.928+10:00</atom:updated><title>Debugging hints &amp; tips</title><description>I've been doing a lot of spelunking with WinDBG recently. There's a lot to know and the documentation can fall short sometimes. &lt;a href="http://blogs.msdn.com/tess/"&gt;Tess's blog&lt;/a&gt; usually has enough entries that you can usually figure things out by looking at her examples and scenarios. I always find myself referring back to her blog and a bunch of other blogs which I referred to in a &lt;a hef="http://steverodgers.blogspot.com/2006_06_01_archive.html#115154677920973353"&gt;previous blog entry&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Primarily, I'm posting this entry as a future helper for myself. Invariably, I draw the information I need from more than one source so I am effectively collating as much of that that useful information here in one place. If that helps anyone else out along the way, then more power to the blog!&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Need to get yourself set up for a WinDBG debug session? Here's what you need to do:&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;1) Create a directory C:\MyLocalSymbols&lt;br /&gt;&lt;br /&gt;2) Install symbols for your operating system to C:\MyLocalSymbols - get symbols from: &lt;a href="http://www.microsoft.com/whdc/devtools/debugging/symbolpkg.mspx"&gt;here&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;3) Install Windows Debugging Tools - get it from: &lt;a href="http://www.microsoft.com/whdc/devtools/debugging/debugstart.mspx"&gt;here&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;4) Set up _NT_SYMBOL_PATH (choose properties on My Computer-&gt;Advanced-&gt;Environment Variables-&gt;New) to SRV*C:\MyLocalSymbols*http://msdl.microsoft.com/download/symbols&lt;br /&gt;This will save you from having to set the path up in WinDBG and will do it globally for the operating system&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;How do I load the CLR debug extension SOS.DLL into WinDBG?&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;1) Type the following command: &lt;br /&gt;.loadby sos mscorwks&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;What is the WinDBG command to get a list of CLR instances of a given type, e.g. System.AppDomain?&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;1) !dumpheap -type System.AppDomain&lt;br /&gt;&lt;br /&gt;e.g. &lt;br /&gt;0:009&gt; !dumpheap -type System.AppDomain&lt;br /&gt; Address       MT     Size&lt;br /&gt;012611b4 790fb998      100     &lt;br /&gt;01261218 790fbdcc       40     &lt;br /&gt;012688c8 790fb998      100     &lt;br /&gt;0126bd28 790fbdcc       40&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;What is the WinDBG command to see the fields of an object?&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;1) Find the object you are interested and use !do addressgoeshere - (use the previous item as a starting point if you don't currently have an object address!)&lt;br /&gt;&lt;br /&gt;In this example we are dumping an AppDomain instance found in the previous example - notice we are using the address column not the MT column!&lt;br /&gt;0:009&gt; !do 012611b4&lt;br /&gt;Name: System.AppDomain&lt;br /&gt;MethodTable: 790fb998&lt;br /&gt;EEClass: 790c3608&lt;br /&gt;Size: 100(0x64) bytes&lt;br /&gt; (C:\WINDOWS\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll)&lt;br /&gt;Fields:&lt;br /&gt;      MT    Field   Offset                 Type VT     Attr    Value Name&lt;br /&gt;790f9ce8  4000184        4        System.Object  0 instance 01284ed8 __identity&lt;br /&gt;7910f540  4000185        8 ....AppDomainManager  0 instance 00000000 _domainManager&lt;br /&gt;790feb44  4000186        c ...ections.Hashtable  0 instance 00000000 _LocalStore&lt;br /&gt;790fbdcc  4000187       10 ...em.AppDomainSetup  0 instance 01261218 _FusionStore&lt;br /&gt;791094f0  4000188       14 ...y.Policy.Evidence  0 instance 00000000 _SecurityIdentity&lt;br /&gt;79124318  4000189       18      System.Object[]  0 instance 00000000 _Policies&lt;br /&gt;7911d470  400018a       1c ...yLoadEventHandler  0 instance 00000000 AssemblyLoad&lt;br /&gt;79116ffc  400018b       20 ...solveEventHandler  0 instance 00000000 TypeResolve&lt;br /&gt;79116ffc  400018c       24 ...solveEventHandler  0 instance 00000000 ResourceResolve&lt;br /&gt;79116ffc  400018d       28 ...solveEventHandler  0 instance 00000000 AssemblyResolve&lt;br /&gt;79116ffc  400018e       2c ...solveEventHandler  0 instance 00000000 ReflectionOnlyAssemblyResolve&lt;br /&gt;791034f8  400018f       30 ....Contexts.Context  0 instance 012687c4 _DefaultContext&lt;br /&gt;7911db24  4000190       34 ...ActivationContext  0 instance 00000000 _activationContext&lt;br /&gt;7911dc44  4000191       38 ...plicationIdentity  0 instance 00000000 _applicationIdentity&lt;br /&gt;7911dd20  4000192       3c ....ApplicationTrust  0 instance 00000000 _applicationTrust&lt;br /&gt;79118234  4000193       40 ...ncipal.IPrincipal  0 instance 00000000 _DefaultPrincipal&lt;br /&gt;79103b10  4000194       44 ...cificRemotingData  0 instance 01268688 _RemotingData&lt;br /&gt;7910d6f8  4000195       48  System.EventHandler  0 instance 00000000 _processExit&lt;br /&gt;7910d6f8  4000196       4c  System.EventHandler  0 instance 00000000 _domainUnload&lt;br /&gt;7911d508  4000197       50 ...ptionEventHandler  0 instance 0129d118 _unhandledException&lt;br /&gt;790fe234  4000198       54        System.IntPtr  0 instance  1345952 _dummyField&lt;br /&gt;7911d974  4000199       58         System.Int32  0 instance        0 _PrincipalPolicy&lt;br /&gt;79105040  400019a       5c       System.Boolean  0 instance        0 _HasSetPolicy&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Need to drill down into a field of an object you just dumped?&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;1) We want to dump the field called _FusionStore of the AppDomain object we just dumped&lt;br /&gt;&lt;br /&gt;2) Use the 'Value' column from the previous !do command for the field called _FusionStore&lt;br /&gt;e.g.&lt;br /&gt;0:009&gt; !do 01261218&lt;br /&gt;Name: System.AppDomainSetup&lt;br /&gt;MethodTable: 790fbdcc&lt;br /&gt;EEClass: 790fbcfc&lt;br /&gt;Size: 40(0x28) bytes&lt;br /&gt; (C:\WINDOWS\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll)&lt;br /&gt;Fields:&lt;br /&gt;      MT    Field   Offset                 Type VT     Attr    Value Name&lt;br /&gt;79124318  40001a3        4      System.Object[]  0 instance 01261240 _Entries&lt;br /&gt;79100ed0  40001a4       20         System.Int32  0 instance        0 _LoaderOptimization&lt;br /&gt;790fa4b0  40001a5        8        System.String  0 instance 00000000 _AppBase&lt;br /&gt;7915cb08  40001a6        c ...DomainInitializer  0 instance 00000000 _AppDomainInitializer&lt;br /&gt;79124318  40001a7       10      System.Object[]  0 instance 00000000 _AppDomainInitializerArguments&lt;br /&gt;7915ce5c  40001a8       14 ...tivationArguments  0 instance 00000000 _ActivationArguments&lt;br /&gt;790fa4b0  40001a9       18        System.String  0 instance 00000000 _ApplicationTrust&lt;br /&gt;79124508  40001aa       1c        System.Byte[]  0 instance 00000000 _ConfigurationBytes&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;How do I dump an array?&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;1) Notice the array in the previous item called _Entries? Use !da addressofobject&lt;br /&gt;&lt;br /&gt;In this example we want to dump the field '_Entries':&lt;br /&gt;&lt;br /&gt;e.g.&lt;br /&gt;0:009&gt; !da 01261240&lt;br /&gt;Name: System.String[]&lt;br /&gt;MethodTable: 79124318&lt;br /&gt;EEClass: 7912488c&lt;br /&gt;Size: 80(0x50) bytes&lt;br /&gt;Array: Rank 1, Number of elements 16, Type CLASS&lt;br /&gt;Element Methodtable: 790fa4b0&lt;br /&gt;[0] 01261530&lt;br /&gt;[1] 01261290&lt;br /&gt;[2] null&lt;br /&gt;[3] null&lt;br /&gt;[4] 012612e4&lt;br /&gt;[5] null&lt;br /&gt;[6] null&lt;br /&gt;[7] null&lt;br /&gt;[8] null&lt;br /&gt;[9] null&lt;br /&gt;[10] null&lt;br /&gt;[11] null&lt;br /&gt;[12] null&lt;br /&gt;[13] null&lt;br /&gt;[14] null&lt;br /&gt;[15] null&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;What is the WinDBG command to find the current managed exception?&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;1) !pe&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;What is the WinDBG command to find the current unmanaged exception?&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;1) .exr -1&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Application seems to generate a lot of exceptions but only one is of concern to you?&lt;/b&gt;&lt;br /&gt;You need to product a dump of the program that you can then debug with WinDBG. You'll need to launch the application and then attach the debugger. In a program I was debugging earlier, I was interested in System.NullReferenceException. &lt;br /&gt;&lt;br /&gt;1) Create a directory on your hard disk called C:\Dumps&lt;br /&gt;&lt;br /&gt;2) Create the following file called trackclr.cfg in the same directory as windbg.EXE (on my machine that was "C:\Program Files\Debugging Tools For Windows"):&lt;br /&gt;&amp;lt;ADPlus&amp;gt;&lt;br /&gt;  &amp;lt;Settings&amp;gt;&lt;br /&gt;    &amp;lt;RunMode&amp;gt;CRASH&amp;lt;/RunMode&amp;gt;&lt;br /&gt;    &amp;lt;Option&amp;gt;Quiet&amp;lt;/Option&amp;gt;&lt;br /&gt;  &amp;lt;/Settings&amp;gt;&lt;br /&gt;  &amp;lt;Exceptions&amp;gt;&lt;br /&gt;    &amp;lt;Option&amp;gt;NoDumpOnFirstChance&amp;lt;/Option&amp;gt;&lt;br /&gt;    &amp;lt;Config&amp;gt;&lt;br /&gt;      &amp;lt;Code&amp;gt;clr&amp;lt;/Code&amp;gt;&lt;br /&gt;      &amp;lt;Actions1&gt;Void&amp;lt;/Actions1&amp;gt;&lt;br /&gt;      &amp;lt;CustomActions1&amp;gt;&lt;br /&gt;    .loadby sos mscorwks;    &lt;br /&gt;    !stoponexception System.NullReferenceException 4;&lt;br /&gt;    .if(@$t4==1)&lt;br /&gt;    {&lt;br /&gt;        .dump /ma /u c:\\Dumps\\NullRef.dmp&lt;br /&gt;    }    &lt;br /&gt;    &amp;lt;/CustomActions1&amp;gt;&lt;br /&gt;      &amp;lt;ReturnAction1&amp;gt;gn&amp;lt;/ReturnAction1&amp;gt;&lt;br /&gt;    &amp;lt;/Config&amp;gt;&lt;br /&gt;  &amp;lt;/Exceptions&amp;gt; &lt;br /&gt;&amp;lt;/ADPlus&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;3) Run the target program (the one you want to debug)&lt;br /&gt;&lt;br /&gt;4) Attach the debugger via the following command line:&lt;br /&gt;adplus -c trackclr.cfg&lt;br /&gt;&lt;br /&gt;5) Crash dump will appear in C:\Dumps&lt;br /&gt;&lt;br /&gt;6) Get some very useful information from the dump via the following command: !analyze -v&lt;br /&gt;&lt;br /&gt;7) From the previous command (!analyze -v), grab the IP address e.g. FAULTING_IP: +957984d and then do a !U addressgoeshere e.g. !U 957984d&lt;br /&gt;This will show you which method and the JIT'd instructions - keep an eye out for the IP itself which is highlighted by WinDBG with chevrons: &gt;&gt;&gt; e.g.&lt;br /&gt;&gt;&gt;&gt; 0957984d 8b01            mov     eax,dword ptr [ecx]&lt;br /&gt;&lt;br /&gt;If you're getting a NullReferenceException and it's on an assembly instruction as seen in the example, then examine the machine registers with the command: r&lt;br /&gt;e.g.&lt;br /&gt;0:009&gt; r&lt;br /&gt;eax=01e05ac4 ebx=00000000 ecx=00000000 edx=00000096 esi=01e05ad0 edi=01dfd144&lt;br /&gt;eip=0957984d esp=07dbd718 ebp=00000096 iopl=0         nv up ei ng nz ac pe cy&lt;br /&gt;cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010297&lt;br /&gt;0957984d 8b01            mov     eax,dword ptr [ecx]  ds:0023:00000000=????????&lt;br /&gt;&lt;br /&gt;In this example, ecx contains all zeros and yet the machine instruction mov     eax,dword ptr [ecx] is trying to dereference the zeros in ecx and assign that to eax - hence an AccessViolation which the CLR will translate to a NullReferenceException&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;You think there is an object of a certain type that is being accessed by more than one thread but can't be sure?&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;1) Produce a crash dump or debug live in WinDBG&lt;br /&gt;&lt;br /&gt;2) Get a list of objects of that type [see above on how to do that]&lt;br /&gt;&lt;br /&gt;3) Pick on one of the objects and see which threads have a reference to it with !gcroot&lt;br /&gt;&lt;br /&gt;This example finds all the threads that have a reference to the AppDomain instance whose address we dumped earlier:&lt;br /&gt;&lt;br /&gt;e.g.&lt;br /&gt;0:009&gt; !gcroot 012611b4&lt;br /&gt;Note: Roots found on stacks may be false positives. Run "!help gcroot" for&lt;br /&gt;more info.&lt;br /&gt;Scan Thread 0 OSTHread 10a8&lt;br /&gt;ESP:12f010:Root:012687c4(System.Runtime.Remoting.Contexts.Context)-&gt;&lt;br /&gt;012611b4(System.AppDomain)&lt;br /&gt;ESP:12f318:Root:0129cf3c(NUnit.ConsoleRunner.ConsoleUi+EventCollector)-&gt;&lt;br /&gt;0129d6b0(System.Runtime.Remoting.ServerIdentity)-&gt;&lt;br /&gt;012687c4(System.Runtime.Remoting.Contexts.Context)&lt;br /&gt;ESP:12f328:Root:01267e48(NUnit.Util.TestDomain)-&gt;&lt;br /&gt;0129cf3c(NUnit.ConsoleRunner.ConsoleUi+EventCollector)-&gt;&lt;br /&gt;0129d6b0(System.Runtime.Remoting.ServerIdentity)&lt;br /&gt;ESP:12f32c:Root:0129cf3c(NUnit.ConsoleRunner.ConsoleUi+EventCollector)-&gt;&lt;br /&gt;012611b4(System.AppDomain)&lt;br /&gt;ESP:12f364:Root:0129d138(NUnit.Util.TestExceptionHandler)-&gt;&lt;br /&gt;0129d118(System.UnhandledExceptionEventHandler)-&gt;&lt;br /&gt;01267e48(NUnit.Util.TestDomain)-&gt;&lt;br /&gt;0129cf3c(NUnit.ConsoleRunner.ConsoleUi+EventCollector)&lt;br /&gt;ESP:12f36c:Root:0129cf3c(NUnit.ConsoleRunner.ConsoleUi+EventCollector)-&gt;&lt;br /&gt;012611b4(System.AppDomain)&lt;br /&gt;ESP:12f370:Root:01267e48(NUnit.Util.TestDomain)-&gt;&lt;br /&gt;012611b4(System.AppDomain)&lt;br /&gt;ESP:12f38c:Root:01267e48(NUnit.Util.TestDomain)-&gt;&lt;br /&gt;012611b4(System.AppDomain)&lt;br /&gt;ESP:12f394:Root:0129cf3c(NUnit.ConsoleRunner.ConsoleUi+EventCollector)-&gt;&lt;br /&gt;012611b4(System.AppDomain)&lt;br /&gt;ESP:12f3d8:Root:0129cf3c(NUnit.ConsoleRunner.ConsoleUi+EventCollector)-&gt;&lt;br /&gt;012611b4(System.AppDomain)&lt;br /&gt;ESP:12f3e0:Root:01267e48(NUnit.Util.TestDomain)-&gt;&lt;br /&gt;012611b4(System.AppDomain)&lt;br /&gt;ESP:12f3e4:Root:01267e48(NUnit.Util.TestDomain)-&gt;&lt;br /&gt;012611b4(System.AppDomain)&lt;br /&gt;Scan Thread 2 OSTHread a74&lt;br /&gt;Scan Thread 4 OSTHread 938&lt;br /&gt;Scan Thread 5 OSTHread 10d0&lt;br /&gt;Scan Thread 8 OSTHread 258&lt;br /&gt;Scan Thread 9 OSTHread ca8&lt;br /&gt;Scan Thread 11 OSTHread 7f4&lt;br /&gt;Scan Thread 14 OSTHread 16a8&lt;br /&gt;Scan Thread 18 OSTHread 31c&lt;br /&gt;Scan Thread 19 OSTHread b84&lt;br /&gt;Scan Thread 20 OSTHread a18&lt;br /&gt;Scan Thread 21 OSTHread 86c&lt;br /&gt;Scan Thread 22 OSTHread 10c0&lt;br /&gt;Scan Thread 23 OSTHread 11c4&lt;br /&gt;Scan Thread 24 OSTHread 1348&lt;br /&gt;Scan Thread 25 OSTHread 3e4&lt;br /&gt;Scan Thread 26 OSTHread de8&lt;br /&gt;DOMAIN(001489A0):HANDLE(WeakLn):8e10fc:Root:012687c4(System.Runtime.Remoting.Contexts.Context)-&gt;&lt;br /&gt;012611b4(System.AppDomain)&lt;br /&gt;DOMAIN(001489A0):HANDLE(Strong):8e1140:Root:012f59e8(System.Threading.Thread)-&gt;&lt;br /&gt;012687c4(System.Runtime.Remoting.Contexts.Context)&lt;br /&gt;DOMAIN(001489A0):HANDLE(Strong):8e1150:Root:0129d6b0(System.Runtime.Remoting.ServerIdentity)-&gt;&lt;br /&gt;012687c4(System.Runtime.Remoting.Contexts.Context)&lt;br /&gt;DOMAIN(001489A0):HANDLE(Strong):8e1154:Root:01284ed8(System.Runtime.Remoting.ServerIdentity)-&gt;&lt;br /&gt;012611b4(System.AppDomain)&lt;br /&gt;DOMAIN(001489A0):HANDLE(Strong):8e11fc:Root:012611b4(System.AppDomain)-&gt;&lt;br /&gt;012611b4(System.AppDomain)&lt;br /&gt;DOMAIN(001489A0):HANDLE(WeakSh):8e12d0:Root:012f59e8(System.Threading.Thread)-&gt;&lt;br /&gt;012611b4(System.AppDomain)&lt;br /&gt;DOMAIN(001489A0):HANDLE(Pinned):8e13fc:Root:02261010(System.Object[])-&gt;&lt;br /&gt;012687c4(System.Runtime.Remoting.Contexts.Context)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Want to find out which threads are running in your application?&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;1) !threads&lt;br /&gt;&lt;br /&gt;e.g.&lt;br /&gt;0:009&gt; !threads&lt;br /&gt;ThreadCount: 17&lt;br /&gt;UnstartedThread: 0&lt;br /&gt;BackgroundThread: 15&lt;br /&gt;PendingThread: 0&lt;br /&gt;DeadThread: 0&lt;br /&gt;Hosted Runtime: no&lt;br /&gt;                                      PreEmptive   GC Alloc           Lock&lt;br /&gt;       ID OSID ThreadOBJ    State     GC       Context       Domain   Count APT Exception&lt;br /&gt;   0    1 10a8 00150b50   2006020 Enabled  00000000:00000000 00198f90     0 STA&lt;br /&gt;   2    2  a74 0015d290      b220 Enabled  00000000:00000000 001489a0     0 MTA (Finalizer)&lt;br /&gt;   4    3  938 0018d488      1220 Enabled  00000000:00000000 001489a0     0 Ukn&lt;br /&gt;   5    4 10d0 001ab710    80a220 Enabled  00000000:00000000 001489a0     0 MTA (Threadpool Completion Port)&lt;br /&gt;   8    5  258 06fa3c90   200b020 Enabled  00000000:00000000 00198f90     0 MTA&lt;br /&gt;   9    6  ca8 06fa48f8      7220 Disabled 00000000:00000000 00198f90     0 STA&lt;br /&gt;  11    7  7f4 06fdce90      b220 Enabled  00000000:00000000 00198f90     0 MTA&lt;br /&gt;  14    8 16a8 001bbcc0   180b220 Enabled  00000000:00000000 001489a0     0 MTA (Threadpool Worker)&lt;br /&gt;  18    9  31c 07029e80   200b220 Enabled  00000000:00000000 00198f90     0 MTA&lt;br /&gt;  19    a  b84 0a885508   200b220 Enabled  00000000:00000000 00198f90     0 MTA&lt;br /&gt;  20    b  a18 0a8b0208   200b220 Enabled  00000000:00000000 00198f90     0 MTA&lt;br /&gt;  21    c  86c 0a8b4160   200b220 Enabled  00000000:00000000 00198f90     0 MTA&lt;br /&gt;  22    d 10c0 0a8b49e8   200b220 Enabled  00000000:00000000 00198f90     0 MTA&lt;br /&gt;  23    e 11c4 0a8b5080   200b220 Enabled  00000000:00000000 00198f90     0 MTA&lt;br /&gt;  24    f 1348 0a8b6b40   200b220 Enabled  00000000:00000000 00198f90     0 MTA&lt;br /&gt;  25   10  3e4 0a8ba158   200b220 Enabled  00000000:00000000 00198f90     0 MTA&lt;br /&gt;  26   11  de8 0a8d0a58   200b220 Enabled  00000000:00000000 00198f90     0 MTA&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Want to see the managed stack of a particular thread?&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;First you need to context switch to the thread of interest in WinDBG, then dump its stack&lt;br /&gt;&lt;br /&gt;1) Context switch to a thread with this command: ~threadnumber s&lt;br /&gt;e.g. from previous !threads call, pick a thread ID from the far left column from the !threads command output&lt;br /&gt;~20 s&lt;br /&gt;&lt;br /&gt;2) Dump the managed call stack for the thread currently switched in:&lt;br /&gt;!clrstack&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Want to see parameters and autos as part of the stack dump?&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;1) Use !clrstack -a&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Application is hung and you want to get a crash dump?&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;1) adplus -hang -pn foo.exe&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5923247-4768627268990667070?l=steverodgers.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://steverodgers.blogspot.com/2007/05/debugging-hints-tips.html</link><author>noreply@blogger.com (Steve J Rodgers)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-5923247.post-1497989373919392121</guid><pubDate>Wed, 11 Apr 2007 14:13:00 +0000</pubDate><atom:updated>2007-06-27T09:58:46.627+10:00</atom:updated><title>Web 2.0 and other musings</title><description>I can't recall where I was or how I heard of the term Web 2.0 - It wasn't that long ago...within the last 6 months for sure. When I first heard it, I wondered what it could be and headed to the usual &lt;a href="http://en.wikipedia.org/wiki/Web_2"&gt;haunt&lt;/a&gt; for an explanation. It all felt a bit wooley to be honest. I then saw an important reference to the &lt;a href="http://www.oreilly.com/pub/a/oreilly/tim/news/2005/09/30/what-is-web-20.html"&gt;source&lt;/a&gt; of the term....that certainly didn't help...The first port of call in my opinion is much better....&lt;br /&gt;&lt;br /&gt;I was having a chat on Messenger with my good friend (and previous business partner) &lt;a href="http://blogs.advantaje.com/blog/kevin/"&gt;Kevin Jones&lt;/a&gt; this evening about what Web 2.0 actually is. We both agreed immediately that it is a Web App that behaves as if it were a thick client app...an &lt;a href="http://en.wikipedia.org/wiki/Ajax_%28programming%29"&gt;Ajax&lt;/a&gt; app for sure. None of this long page load malarky...highly responsive...just like every google app...just like a thick client app.&lt;br /&gt;&lt;br /&gt;What else? I think that Google dumping web services as the programmable interface to their business is a sign. I'm starting to wonder whether web services are going to be important in the long term with Ajax and JSON lurking in the background. I think web services are a master stroke for linking together systems that otherwise couldn't talk to one another - but supposing everything starts to converge on Web 2.0? The industry will never give up on the web as the most important platform - it will only get better...The web already is the one platform.&lt;br /&gt;&lt;br /&gt;I also started thinking about ASP.NET AJAX. I have not programmed it yet but it's an add on to ASP.NET. In other words, Web 2.0 as a metaphor for Web apps was not in the minds of the ASP.NET architects at Redmond when they set about designing the replacement technology for ASP. This started me thinking about Ruby On Rails...this is more recent than ASP.NET so maybe this has an architecture designed with Web 2.0 as it's central metaphor? I have no idea yet as I haven't had a chance to look at it, but I will be doing so shortly!&lt;br /&gt;&lt;br /&gt;Everything is heading towards being free to the end user on the web. I'm fairly certain I read that in a &lt;a href="http://www.paulgraham.com"&gt;Paul Graham&lt;/a&gt; essay but don't ask me which one!! This feels right to me. I never pay for something on the web if I can find a way to get it for free with a little bit of extra googling. This is important. I think it's a sign and I certainly hadn't been thinking about it until I read that. &lt;br /&gt;&lt;br /&gt;That train of thought started me thinking about open source software - PHP, MySQL, Ruby on Rails, Mono..etc...no matter how hard Redmond tries to run away with technology, these guys follow with free software / software tools...I was reading &lt;a href="http://en.wikipedia.org/wiki/AdWords"&gt;today&lt;/a&gt; that Adsense is built with MySQL as it's backend DB. &lt;br /&gt;&lt;br /&gt;There are so many sites out there on Apache (free), running PHP (free) connecting to MySQL (free) that it's hard to ignore it. The end user's apparent running costs must be lower - I'm assuming that the software dev team are good and know their stuff. Why wouldn't you use it? Clearly, it scales!&lt;br /&gt;&lt;br /&gt;I don't really have any conclusions to draw from these musings but I am getting a very strong sense of which way the wind is blowing.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5923247-1497989373919392121?l=steverodgers.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://steverodgers.blogspot.com/2007/04/web-20-and-other-musings.html</link><author>noreply@blogger.com (Steve J Rodgers)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-5923247.post-4746989402019920398</guid><pubDate>Wed, 28 Mar 2007 06:35:00 +0000</pubDate><atom:updated>2007-03-28T16:47:43.983+10:00</atom:updated><title>Being compared to when you didn't expect it</title><description>I've been doing a lot of migration work on a .NET v1.1 code base to .NET 2.0 recently. I just ran into a (gnarly) documented change in the implementation of ArrayList.Contains(object item) that was causing a unit test to fail....here's the relevant extract from the remarks section towards the end of the document [1] (http://msdn2.microsoft.com/en-us/library/system.collections.arraylist.contains.aspx)&lt;br /&gt;&lt;br /&gt;In our case we were passing in items that had overidden Object.Equals. Since this method is now invoked by ArrayList.Contains() in .NET v2.0 but was not previously in .NET v1.1, our implementation of Object.Equals was incorrect for this scenario.&lt;br /&gt;&lt;br /&gt;[1] &lt;br /&gt;"Starting with the .NET Framework 2.0, this method uses the collection’s objects’ Equals and CompareTo methods on item to determine whether item exists. In the earlier versions of the .NET Framework, this determination was made by using the Equals and CompareTo methods of the item parameter on the objects in the collection"&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5923247-4746989402019920398?l=steverodgers.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://steverodgers.blogspot.com/2007/03/being-compared-to-when-you-didnt-expect.html</link><author>noreply@blogger.com (Steve J Rodgers)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-5923247.post-208479968736779560</guid><pubDate>Tue, 20 Feb 2007 08:40:00 +0000</pubDate><atom:updated>2007-02-20T18:48:46.685+10:00</atom:updated><title>The Wingsuit</title><description>The race is on to develop a wingsuit that allows the wearer to do away with a parachute entirely...according to &lt;a href="http://www.saab.com.sg/main/GLOBAL/en/salomon_soul_flyers.php"&gt;this&lt;/a&gt; article, the wingsuit increases the horizontal component from normal freefall rate of 0.5m to wingsuit wearer 3.0m per 1.0m decent&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.youtube.com/watch?v=tqW6O_dcF2M"&gt;Truly Amazing I&lt;/a&gt;&lt;br /&gt; &lt;br /&gt;&lt;a href="http://www.youtube.com/watch?v=xYrId4WlR4Q"&gt;Truly Amazing II&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5923247-208479968736779560?l=steverodgers.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://steverodgers.blogspot.com/2007/02/wingsuit.html</link><author>noreply@blogger.com (Steve J Rodgers)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-5923247.post-1997280657873355525</guid><pubDate>Thu, 04 Jan 2007 02:00:00 +0000</pubDate><atom:updated>2007-01-04T12:07:20.201+10:00</atom:updated><title>Debugging Internet Explorer hosted Windows Forms Controls</title><description>Our product for historical reasons has some .NET v1.1 Windows Forms user controls embedded in ASP.NET pages.&lt;br /&gt;&lt;br /&gt;Running these pages on a machine that has .NET v2.0 installed causes things to not work. Basically the unmanaged host iexplore.exe has to pick a version of the CLR to load when it is about to load the controls and it will pick the latest and greatest v2.0 in our case. This of course, is not what we want. It is possible to constrain the options by having an iexplore.exe.config that specifies the versions it is allowed to choose from. In our case, the config file looks like this:&lt;br /&gt;&lt;br /&gt;&amp;lt;configuration&amp;gt;&lt;br /&gt;   &amp;lt;startup&amp;gt;&lt;br /&gt;      &amp;lt;supportedRuntime version="v1.1.4322"/&amp;gt;&lt;br /&gt;   &amp;lt;/startup&amp;gt;&lt;br /&gt;&amp;lt;/configuration&amp;gt;&lt;br /&gt;&lt;br /&gt;A useful tip in debugging Windows Forms controls embedded in this way is to activate &lt;a href="http://support.microsoft.com/kb/313892"&gt;IEHost logging&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5923247-1997280657873355525?l=steverodgers.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://steverodgers.blogspot.com/2007/01/debugging-internet-explorer-hosted.html</link><author>noreply@blogger.com (Steve J Rodgers)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-5923247.post-4836021505241455410</guid><pubDate>Wed, 22 Nov 2006 01:17:00 +0000</pubDate><atom:updated>2006-11-22T11:20:14.580+10:00</atom:updated><title>Compilation Error: ‘The key container name ‘Blah’ does not exist’</title><description>I just spent a couple of hours solving this one – when your AssemblyInfo.cs file references a key container (e.g. [assembly: AssemblyKeyName("Blah")]) that doesn’t exist or it doesn’t have sufficient access permissions you’ll get this error.&lt;br /&gt;&lt;br /&gt;Fixing this problem used to involve going to the registry entry: HKLM\Software\Microsoft\Cryptography\MachineKeys and setting the permissions to give yourself access to all the keys in the key store – (well you are logged in as Admin after all ;)&lt;br /&gt;&lt;br /&gt;The key store has moved from the registry to the file system with Windows 2000 apparently – It’d been a while since I’d been in there as you can tell. You want to go to:&lt;br /&gt;C:\Documents and Settings\All Users\Application Data\Microsoft\Crypto\RSA\MachineKeys&lt;br /&gt;&lt;br /&gt;...and change the DACL to give yourself permissions.&lt;br /&gt;&lt;br /&gt;In my case, the key container was effectively an orphan – the account that created it must have been deleted and so I had to take ownership of the orphaned file (as admin) and set the DACL up to give myself permissions&lt;br /&gt;&lt;br /&gt;As a test for the future I decided to try to access that directory from my Vista box. As I surfed to my Vista ‘C:\Documents and Settings’ folder I was prompted for elevation – I accepted the elevation but the DACL killed the elevation according to the UI – So I checked out the security for the folder and I was marked as having ‘Full Control’ – geez – I hope I don’t ever see this compilation error when I move over to Vista&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5923247-4836021505241455410?l=steverodgers.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://steverodgers.blogspot.com/2006/11/compilation-error-key-container-name.html</link><author>noreply@blogger.com (Steve J Rodgers)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-5923247.post-2831811947951238847</guid><pubDate>Fri, 17 Nov 2006 13:14:00 +0000</pubDate><atom:updated>2006-11-17T23:17:39.963+10:00</atom:updated><title>the death of fastfood as we know it</title><description>I have been thinking for a long while now that fast food will one day become what smoking has now become - a thing that is discouraged and not allowed in public places. When I read &lt;a href="http://news.bbc.co.uk/1/hi/health/6154600.stm"&gt;this&lt;/a&gt; article on the BBC news website, I had to smile.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5923247-2831811947951238847?l=steverodgers.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://steverodgers.blogspot.com/2006/11/death-of-fastfood-as-we-know-it.html</link><author>noreply@blogger.com (Steve J Rodgers)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-5923247.post-8406579148558654210</guid><pubDate>Mon, 25 Sep 2006 06:34:00 +0000</pubDate><atom:updated>2006-09-25T16:37:52.608+10:00</atom:updated><title>Chris Brumme blogs again...</title><description>&lt;a href="http://blogs.msdn.com/cbrumme"&gt;Chris Brumme&lt;/a&gt; has posted to his blog after a 2 year hiatus...I wonder if he'll start blogging on a more frequent basis from now on?...one can only hope so.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5923247-8406579148558654210?l=steverodgers.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://steverodgers.blogspot.com/2006/09/chris-brumme-blogs-again.html</link><author>noreply@blogger.com (Steve J Rodgers)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-5923247.post-8369278183303015045</guid><pubDate>Mon, 18 Sep 2006 22:49:00 +0000</pubDate><atom:updated>2006-09-19T08:50:52.576+10:00</atom:updated><title>Sticky silicon</title><description>From the BBC News website:&lt;a href="http://news.bbc.co.uk/2/hi/technology/5356636.stm"&gt;Sticky silicon&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5923247-8369278183303015045?l=steverodgers.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://steverodgers.blogspot.com/2006/09/sticky-silicon.html</link><author>noreply@blogger.com (Steve J Rodgers)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-5923247.post-115560722851245238</guid><pubDate>Tue, 15 Aug 2006 01:49:00 +0000</pubDate><atom:updated>2007-07-17T23:19:37.356+10:00</atom:updated><title>SQL Server 2005 PIVOT woes</title><description>I spent a morning playing with the new SQL Server 2005 PIVOT command in T-SQL.&lt;br /&gt;&lt;br /&gt;I created a new database that has 2 columns: ID(int), Field(nvarchar(50), DataValue(nvarchar(50))&lt;br /&gt;&lt;br /&gt;I put some data in:&lt;br /&gt;insert into SomeData values('Shift', 'Day Shift')&lt;br /&gt;insert into SomeData values('Shift', 'Night Shift')&lt;br /&gt;insert into SomeData values('Shift', 'Day Shift')&lt;br /&gt;insert into SomeData values('Shift', 'Morning Shift')&lt;br /&gt;&lt;br /&gt;and then issued my PIVOT command:&lt;br /&gt;SELECT ID, [Day Shift] AS DayShift, [Morning Shift] AS MorningShift, [Night Shift] AS NightShift FROM SOMEDATA &lt;br /&gt;PIVOT &lt;br /&gt;(&lt;br /&gt;MIN([Field])&lt;br /&gt;FOR DataValue IN ([Day Shift], [Morning Shift], [Night Shift])&lt;br /&gt;) p&lt;br /&gt;&lt;br /&gt;Things to watch out for...you must alias the PIVOT with a variable even if you don't use it anywhere - in my case I chose the letter p&lt;br /&gt;&lt;br /&gt;The items in the FOR list cannot be calculated from a subquery so you must list them :(&lt;br /&gt;&lt;br /&gt;If you import a SQL Server 2000 database that has the same schema as my example and then try to issue the above command, you'll get back a cryptic error like this:&lt;br /&gt;Msg 102, Level 15, State 1, Line 5&lt;br /&gt;Incorrect syntax near '('.&lt;br /&gt;&lt;br /&gt;You need to change the compatibility level of the database to SQL Server 2005 otherwise the functionality is restricted to SQL Server 2000 - PIVOT command is not available for SQL Server 2000. It took me a long time to figure this out because that error message is not much use! You change the compatibility level to SQL Server 2005 with sp_dbcmptlevel e.g.&lt;br /&gt;EXEC sp_dbcmptlevel 'RevesbyProjectData', '90';&lt;br /&gt;&lt;br /&gt;where the first parameter is the name of the database and the second parameter is the version of SQL Server: 80 is 2000 and 90 is 2005&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5923247-115560722851245238?l=steverodgers.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://steverodgers.blogspot.com/2006/08/sql-server-2005-pivot-woes.html</link><author>noreply@blogger.com (Steve J Rodgers)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>2</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-5923247.post-115476308556668264</guid><pubDate>Sat, 05 Aug 2006 07:29:00 +0000</pubDate><atom:updated>2007-09-28T00:54:03.842+10:00</atom:updated><title>Internet memory lane</title><description>Interesting trip down &lt;a href="http://news.bbc.co.uk/2/hi/technology/5243862.stm"&gt;internet memory lane&lt;/a&gt; - Seems hard to believe in August 1995 there were only 18,957 web sites in the world.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5923247-115476308556668264?l=steverodgers.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://steverodgers.blogspot.com/2006/08/internet-memory-lane.html</link><author>noreply@blogger.com (Steve J Rodgers)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-5923247.post-115309707237110759</guid><pubDate>Mon, 17 Jul 2006 00:41:00 +0000</pubDate><atom:updated>2007-09-28T00:54:03.848+10:00</atom:updated><title>ALT-TAB Vista</title><description>I just found out that ALT-TAB now includes the mouse in Vista...just do a single ALT-TAB, keep the ALT key pushed down and then move the mouse into the ALT-TAB area and hover over whichever item you're interested in and it automatically selects that item&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5923247-115309707237110759?l=steverodgers.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://steverodgers.blogspot.com/2006/07/alt-tab-vista.html</link><author>noreply@blogger.com (Steve J Rodgers)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-5923247.post-115241682546597248</guid><pubDate>Sun, 09 Jul 2006 03:47:00 +0000</pubDate><atom:updated>2007-09-28T00:54:03.859+10:00</atom:updated><title>Getting to Low Earth Orbit</title><description>If you have plans to achieve &lt;a href="http://en.wikipedia.org/wiki/Low_Earth_orbit"&gt;Low Earth Orbit&lt;/a&gt; then &lt;a href="http://www.spacefuture.com/archive/getting_to_low_earth_orbit.shtml"&gt;this&lt;/a&gt; is essential reading!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5923247-115241682546597248?l=steverodgers.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://steverodgers.blogspot.com/2006/07/getting-to-low-earth-orbit.html</link><author>noreply@blogger.com (Steve J Rodgers)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-5923247.post-115154677920973353</guid><pubDate>Thu, 29 Jun 2006 01:57:00 +0000</pubDate><atom:updated>2007-09-28T00:54:03.871+10:00</atom:updated><title>Debugging release apps</title><description>Debugging is actually quite hard in a release environment. I have learned a great deal about how to do this by reading the following blogs:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.mtaulty.com/blog/(xdsndm554gz05wefg2dwf045)/default.aspx"&gt;Mike Taulty&lt;/a&gt; has three good blogs:&lt;br /&gt;&lt;a href="http://mtaulty.com/blog/(cdnluciha0ucbzjozkrkstjn)/archive/2004/08/03/608.aspx"&gt;Part 1&lt;/a&gt;, &lt;a href="http://mtaulty.com/blog/(u1wmgr55i3eqi045ui4nmf45)/archive/2004/08/03/609.aspx"&gt;Part 2&lt;/a&gt; and &lt;a href="http://mtaulty.com/blog/(otdsbaqprgnbwlaqkgexra2a)/archive/2004/08/06/628.aspx"&gt;Part 3&lt;/a&gt;&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;br /&gt;&lt;a href="http://blogs.msdn.com/tess/default.aspx"&gt;Tess Ferrandez&lt;/a&gt; has the ultimate blog for debugging managed apps&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;br /&gt;&lt;a href="http://www.wintellect.com/Weblogs/CategoryView,category,John%20Robbins.aspx"&gt;John Robbins&lt;/a&gt; rates Tess &lt;a href="http://www.wintellect.com/Weblogs/DoYouReallyWantToLearnAboutSOS.aspx"&gt;above himself&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5923247-115154677920973353?l=steverodgers.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://steverodgers.blogspot.com/2006/06/debugging-release-apps.html</link><author>noreply@blogger.com (Steve J Rodgers)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-5923247.post-115144966895347365</guid><pubDate>Tue, 27 Jun 2006 23:01:00 +0000</pubDate><atom:updated>2007-09-28T00:54:03.878+10:00</atom:updated><title>TLA decoder</title><description>Occasionally I come across a TLA and have no idea what it means - by chance I found a web site which has some pretty good suggestions:&lt;br /&gt;&lt;br /&gt;http://www.acronymfinder.com/&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5923247-115144966895347365?l=steverodgers.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://steverodgers.blogspot.com/2006/06/tla-decoder.html</link><author>noreply@blogger.com (Steve J Rodgers)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-5923247.post-115085153038710390</guid><pubDate>Wed, 21 Jun 2006 00:56:00 +0000</pubDate><atom:updated>2007-09-28T00:54:03.884+10:00</atom:updated><title>500 GHz anyone??</title><description>If you have access to some sophisticated cooling equipment (I was tempted to say cool equipment but thought better of it) and some non silicon material then it's possible to &lt;a href="http://news.bbc.co.uk/2/hi/technology/5099584.stm"&gt;increase&lt;/a&gt; the processing speed to 500 GHz&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5923247-115085153038710390?l=steverodgers.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://steverodgers.blogspot.com/2006/06/500-ghz-anyone.html</link><author>noreply@blogger.com (Steve J Rodgers)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item></channel></rss>