Mad Props!

Omniscience is just a Google-search away.

Login

You're reading Mabsterama, the weblog of Matt Hamilton. Enjoy your stay.

Holiday Time!

One last blog post before we fly out to the US on Saturday.

Things I'll miss while I'm away:

  • Constantly monitoring my reputation on Stack Overflow
  • Constantly refreshing Twitter to see what people (some of whom I've never even met) are up to
  • AWDNUG next Tuesday, where Kym will be talking about SQL Server security
  • My Xbox 360

Things I won't miss:

  • Moving office furniture at work while the renovations are going on
  • Doing work at work after the renovations have finished
  • Having to save money for this holiday :)

So anyway, this blog will probably be darker than usual for the next two weeks. If I get a chance to jump on a PC over there I'll post, but otherwise brace yourself for some photos etc later in the month.

Dynamic Type Instantiation on the Compact Framework

Someone on Stack Overflow today asked how to dynamically instantiate a type that doesn't have a default constructor on the .NET Compact Framework. As an example, let's say you have a type called "Foo" which takes some parameters in its constructor:

public class Foo
{
    public Foo(string s, int i)
    {
        // do stuff with s, i
    }
}

So now with no information other than the name of the type as a string ("Application1.Foo" in this case), you want to spin up an instance of that type.

On the full framework you'd use an overload of Activator.CreateInstance, like this:

string s = "Application1.Foo";
Type t = Assembly.GetExecutingAssembly().GetType(s);
Foo f = Activator.CreateInstance(t, "hello", 17) as Foo;

But on the Compact Framework, the overload for CreateInstance that lets you pass extra parameters doesn't exist. Instead, you have to use the GetConstructor method to determine the correct constructor to use. Here's an extension method for the Assembly type to make it easy!

public static class AssemblyExtensions { static object CreateInstance(this Assembly a,

string typeName, params object[] pars) { var t = a.GetType(typeName); var c = t.GetConstructor(pars.Select(p => p.GetType()).ToArray()); if (c == null) return null; return c.Invoke(pars); } }

Note the use of LINQ's "Select" method to turn the parameters into an array of types! Pretty funky! Now you can just type this, even on the Compact Framework:

Foo f = Assembly.GetExecutingAssembly()

.CreateInstance("SmartDeviceProject1.Foo", "hello", 17) as Foo;

Did you get his permission?

Those who know me well enough know that I hate, with the fire of a thousand suns, companies whose business is based on mobile phone ringtones, SMS scams etc. To me they're only one step up from spammers, and it burns me every time I see one of their horrifically-bad advertisements on TV.

The other day one such ad came on, describing how you can find your "perfect match" simply by sending your name via SMS to the number on your screen. You know the drill. Anyway, hidden in the small print at the bottom of the screen (the bit that tells you that you're surrendering your firstborn child if you so much as pick up your phone after watching this ad) was this text:

ask bill ayers permission

Do I need to write "sic" here? I want to make it clear that none of that is a typo.

So after reading that, I jokingly posted this to Twitter:

Who is Bill Ayers? There's a dodgy SMS-dating ad on TV right now whose fine print includes the text, "bill ayers permission".

Nobody replied, but something magical happened. Within 24 hours, this story appeared on Digg: Obama Ayers Ad Responds To McCain Attack. It turns out that Bill Ayers is some sort of political activist from the US!

So now I'm really confused! A slimy SMS subscription company in Australia is demanding that you get William Ayers' permission before sending them your name! Ok, they forgot to include the trailing apostrophe, but their business model suggests that they're slightly retarded, so I can forgive them that.

What's the story, Bill Ayers? Why do I need your permission!!??

Tropic Thunder, Stack Overflow and More

It occurred to me this morning that I haven't made a simple "personal news" post here for a while, so here's all the goss.

This weekend was my mother-in-law Di's 60th birthday, and we went out to the local Chinese restaurant to celebrate. Chinese food is a little bit passe nowadays if you ask me, but the previous generation still seems to think it's the bee's knees, so we were happy to accommodate. Unfortunately the restaurant was just abysmal. Despite us having booked for 30 people, they only had one waitress working, so it was nearly an hour before we even had our orders taken. Then, after the three other tables in our party had all finished their main meals, we were asked if we wanted any dessert. This, mind you, was before we had been served our own main meals! It was obvious that they'd completely forgotten them, and the end-result was a rushed, tasteless array of meals that we shouldn't have had to pay for. What's worse is that our table included Di herself. Heck of a birthday party. And the fact that they still charged us full price really rubs me the wrong way. I'm kicking myself for paying. For Albury folks reading this, I'm talking about Ocean City restaurant in Lavington, so dine there at your own peril.

Sal and I caught Tropic Thunder yesterday and thoroughly enjoyed it. As many have written, Robert Downey Jr stole the show. His Australian accent is quite appalling, but it works well within the film's satirical context. Unfortunately I found his "southern black man" accent almost impossible to understand, although that may have been intentional.

Over the past few weeks I've been almost completely caught up in the fury that is Stack Overflow, the new forum/wiki project from Jeff Atwood. If you're a software developer then you're probably all over this already, and if you're not then you probably aren't interested, but I will say that the "reputation" and "badge" system (analogous to Xbox Live's "gamerscore" and "achievements") have made this site very addictive. It makes you want to answer questions, which means it's a very helpful ecosystem.

At work, we're in the middle of an office renovation which will bring all developers together into a shared workspace. It's a step back in that a couple of us lose our own private offices, but we gain our own "brainstorming" meeting room and a lot of wall space for whiteboards, so it should make for a collaborative, productive environment.

And lastly, we fly out to the US in two weeks' time for a 12 night holiday with both sets of parents. Sal and I decided at the beginning of the year that we'd take our parents to Vegas and show them where we were married. It was a way to take the parents away from it all for a while and share some quality time. Since making that decision, some others have decided to tag along, which has kind of defeated the purpose of the trip, but we'll try to make lemonade and have a good time.

Concatenate a list with ToConcatenatedString

I've been posting a few extension methods here lately, so I thought I'd throw another into the mix. This set of ToConcatenatedString methods will take a list of objects and return a delimited string. It gives you the option of specifying your own delimiter (the default is ", ") and your own custom "toString" function if you want to do something other than call .ToString() on each object.

public static class ConcatenationExtensions { public static string ToConcatenatedString<T>(this IEnumerable<T> list,

string delimiter, Func<T, string> toString) { if (list == null || list.Count() == 0) return string.Empty; var sb = new StringBuilder(toString(list.First())); foreach (var t in list.Skip(1)) { sb.Append(delimiter); sb.Append(toString(t)); } return sb.ToString(); } public static string ToConcatenatedString<T>(this IEnumerable<T> list,

string delimiter) { return list.ToConcatenatedString(delimiter, t => t.ToString()); } public static string ToConcatenatedString<T>(this IEnumerable<T> list) { return list.ToConcatenatedString(", ", t => t.ToString()); } }

So now you can take, for example, a list of Customers, and say:

Console.WriteLine(custs.ToConcatenatedString("\n",

c => c.Name + " " + c.Address));

Handy for logging or quickly showing a message to the user.

Enter to Tab as an Attached Property

Updated! As suggested by Eric Burke in the comments, I'm now handling the "Unloaded" event and unhooking the event handlers there, so the elements are properly cleaned up by the garbage collector. Thanks Eric!

A while ago I posted about a trick to make your WPF applications treat the enter key as a tab, and shift focus to the next available control. Paul commented that it should be possible to do that using an attached property, and I agreed, but didn't know how.

Well, now I do.

I'll post the full code for the property itself below, but first, its usage. Firstly you'll need to add an xmlns declaration to the top of your form pointing to the class' namespace. Usually this is just the namespace of your application, like WpfApplication1. I like to call this XML namespace "my". So your window's declaration ends up looking like:

<Window x:Class="WpfApplication1.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:my="clr-namespace:WpfApplication1"
    Title="Window1">

Next you want to find the container control (usually a Grid or StackPanel) in which all your data-entry controls live, and add the attached property to it, like this:

<StackPanel my:EnterKeyTraversal.IsEnabled="True">

Now all the controls within that StackPanel will treat the Enter key as a tab! Once the focus shifts out of the StackPanel the Enter key reverts to its normal behaviour, which is nice because the very next control will probably be an "OK" button, and the user will want to be able to press Enter to click it.

Here's the complete class declaration to give you the EnterKeyTraversal.IsEnabled property. Have fun!

public class EnterKeyTraversal { public static bool GetIsEnabled(DependencyObject obj) { return (bool)obj.GetValue(IsEnabledProperty); } public static void SetIsEnabled(DependencyObject obj, bool value) { obj.SetValue(IsEnabledProperty, value); } static void ue_PreviewKeyDown(object sender, System.Windows.Input.KeyEventArgs e) { var ue = e.OriginalSource as FrameworkElement; if (e.Key == Key.Enter) { e.Handled = true; ue.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next)); } } private static void ue_Unloaded(object sender, RoutedEventArgs e) { var ue = sender as FrameworkElement; if (ue == null) return; ue.Unloaded -= ue_Unloaded; ue.PreviewKeyDown -= ue_PreviewKeyDown; } public static readonly DependencyProperty IsEnabledProperty = DependencyProperty.RegisterAttached("IsEnabled", typeof(bool),

typeof(EnterKeyTraversal), new UIPropertyMetadata(false, IsEnabledChanged)); static void IsEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var ue = d as FrameworkElement; if (ue == null) return; if ((bool)e.NewValue) { ue.Unloaded += ue_Unloaded; ue.PreviewKeyDown += ue_PreviewKeyDown; } else { ue.PreviewKeyDown -= ue_PreviewKeyDown; } } }

Collection Implementations as Dependencies

We're working on a series of classes here at work which form a domain model which will some day be accessed from both a PC client (using Windows Presentation Foundation) and a mobile client (using the .NET Compact Framework).

Targeting two different frameworks from the same set of classes is usually not too big a challenge, but we recently found one case that stumped us.

Imagine, if you will, that you have a class called "Order" which stores a collection of "OrderItem" objects. So the order itself has the customer, the date etc, and each item within the order has a product, quantity etc. We define our order's items property thusly:

private IList<OrderItem> _items = new List<OrderItem>();
public IList<OrderItem> Items { get { return _items; } }

Pretty straight forward, really. However, we decided that we wanted to bind directly to the Items property of our order from within our WPF client, and we therefore wanted to make use of .NET 3.0's ObservableCollection<T> property. So our first instinct was to simply do this:

private IList<OrderItem> _items = new ObservableCollection<OrderItem>();
public IList<OrderItem> Items { get { return _items; } }

Sounds reasonable, right? And it is, until you realise that ObservableCollection<T> is not available on the compact framework. Now our class won't compile to a mobile version of the assembly. To get nice collection data-binding on the compact framework you pretty much have to use BindingList<T>.

We tossed around a few solutions. One idea was to make a "CollectionFactory" class which would have a different implementation in the "desktop" version of the assembly and the "mobile" version. The code would then morph into something like this:

private IList<OrderItem> _items = CollectionFactory.New<OrderItem>();
public IList<OrderItem> Items { get { return _items; } }

I still believe that this idea would work, but now I'm considering another approach. We've learned a lot recently about dependency injection, and have been structuring our classes in such a way that each class accepts its dependencies as constructor parameters. I'm starting to wonder now whether the implementation of a collection should be a dependency too. So now instead of constructing the _items list in its declaration, we would accept it as a parameter to the class itself, like this:

class Order
{
    public Order(IList<OrderItem> items)
    {
        _items = items;
    }

    public Order() : this(new List<OrderItem>())
    {
    }

 

There are drawbacks to this approach. The calling code could pass in a non-empty list. I guess we could call Clear() on the list first, but it still seems hackish. The calling code could also construct more than one Order instance with the same list of OrderItems, which is a bit ugly too.

Another approach would be generics:

class Order<T> where T : IList<OrderItem>, new()
{
    public Order()
    {
        _items = new T();
    }

And this works nicely but makes the code to instantiate a new order look pretty messy. Or we could use lambdas and just ask for how to make a new list:

class Order
{
    public Order(Func<IList<OrderItem>> itemsGenerator)
    {
        _items = itemsGenerator();
    }

This is kinda cool too, but has similar problems to simply passing the list in as an object.

One last approach would be to define our own ObservableCollection<T> class in the mobile version of the assembly, by simply deriving it from BindingList<T>. If we never explicitly used any of ObservableCollection<T>'s unique methods or properties from within our assembly then that could work.

Have you solved this particular problem? Hey Microsoft! When can we have ObservableCollection<T> and INotifyCollectionChanged in the compact framework?

Usability of Pigeon-Holes

Everyone knows what a pigeon-hole is, right? It's a term for the trays or boxes in offices that are assigned to people or groups so that you can drop mail off for someone without having to know where their office is. I'm defining the term because I honestly don't know if it's an Australian term or if it's used overseas.

Anyway, we recently got some new ones here at work, and I felt the need to post and rant about the labelling system that some brainiac here has come up with.

Firstly, instead of the individual shelves being labelled with the name of the person (or group) that the shelf belongs to, they are instead assigned a number (from one to about 35). A "legend" mapping numbers to names has been printed out and stuck on the wall nearby. So straight away you can't just look at the shelves to determine where to drop your mail - you have to shoot your attention back and forth between the printed list and the shelves.

Secondly, the numbers run top to bottom instead of left to right, contrary to how the western world thinks when reading. So you're looking for #19 - you find #20 and move one to the left, and it's #13.

And lastly, the numbers are actually on the shelf above the one you want. So you find the shelf labelled "19" and go to put your mail onto it, and then you have to remember that the label actually applies to the shelf below the one it's stuck to.

Basically they've turned what should be a very simple exercise - finding someone's name and putting your mail on that shelf - into a complex, multi-step process. It's a small thing, but the small things add up.

Type Inference for Constants

In C# 3.0 (part of .NET 3.5) we were introduced to a new keyword: var. The var keyword enabled a really nice feature called "type inference", whereby you can declare a variable without having to explicitly state its type. In trivial examples like this, it doesn't feel like it saves you much:

var i = 3; // i is an int

... but where it saves a lot of typing and redundancy is when you have a reasonably complex type, like this:

var x = new Dictionary<string, Func<string, IList<int>>>();

This saves you from having to repeat a long type name on both sides of the "=" sign, which adds to code readability.

Now, some would argue that var can be evil. For example, when you use it like this, it's very difficult for the reader of your code to tell what type your variable is:

var foo = DoStuff();

... but then, that's more a problem of method naming than anything. If that method had been called "GetFoo" then perhaps it would be more obvious what type "foo" is.

Anyway, a feature that has been around in Pascal forever and would be handy to have in C# is type inference for constants. Right now if you want to declare a constant, you use the const keyword as a modifier for a variable declaration, like this:

const float pi = 3.14159;

But since constants have to be initialised at the same time that they're declared, it makes sense to me to adapt the type inference rules to apply to the const keyword too. Then we'd have the option of declaring constants like this:

const pi = 3.14159;
It's a small change, but I don't think it would be particularly hard to pull off. What do you think?

Campaign for a Free EPG in Australia

Last week saw the launch of MyEPG.com.au, a web site devoted to the freeing of the electronic program guide (EPG) data for Australian free-to-air digital TV. As I've written in the past, the commercial FTA television networks here in Australia actually use copyright law to protect their guide data. It's astounding, in that by their definition it should actually be illegal to program your VCR based on the listings in your local newspaper!

As part of the MyEPG campaign, they suggest that you use one of their form letters to contact your local member and bring the issue to their attention. I didn't use a form letter, but I did contact Sussan Ley, my local representative, and let her know about the site. I was amazed to get a personal reply from Sussan later that evening (6:45pm, no less) saying that she would be contacting the federal minister for communications on my behalf! I've even since received a letter in the (snail) mail from her office promising to forward me any future correspondence she receives on the subject!

I really hope the MyEPG campaign works. As a user of Windows Media Center I rely on Free*EPG for my data, and while those guys do a great job, the information should be free and not need any third-party intervention to make it available.

So if you're in Australia and use FTA digital TV, jump on over to the MyEPG site and sign their petition. Every voice helps!