syndicate

Runtime handler registration in .NET

I've been working on some home automation software in C# for a friend and hit a bit of a stumbling block the other day. I needed to be able to register some message handlers for this application at runtime.

To do this, one needs to use the reflection framework - this allows you to inspect the assembly types and metadata at runtime, and is useful for this type of thing. This isn't exactly rocket science, and one can quickly throw together a quick example to discover each of the types that implement a given Interface/Subclass and make a method call to a static method on the class:

// Find all the types in this AppDomain that implement the IMessage interface
foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
{
    foreach (Type type in assembly.GetTypes())
    {
        if( type.IsSubclassOf( typeof(MessageBase) ) )
        {
            MethodInfo method = type.GetMethod("ImplementsMessage");
            MessageType msgType = (MessageType)method.Invoke(null, null);
            _messageHandlers.Add(msgType, type);

             Query the type and see what protocol message it handles
            try
            {
                // If any bit of this fails, we'll fail silently which is OK
                ConstructorInfo constructor = type.GetConstructor(new Type[0]);
                IMessage obj = (IMessage)constructor.Invoke(new object[0]);
                _messageHandlers.Add(obj.ImplementsMessage(), type);
            }
            catch
            {
                continue;
            }
        }
    }
}

The above example will call the static ImplementsMessage method on each class that is discovered that is a subclass of MessageBase.

This is well and goodly, but the problems start when you try and declare the ImplementsMessage in either an Interface or superclass. In this case, I have an Interface IMessage that I want all message handlers to implement. Interfaces and base classes are good, as we know, for defining a concrete contract to ensure that all of our classes implement the methods expected of them by the rest of the code - and are a key part of the design of this library.

Unfortunately, in any of the .NET languages - you cannot define static members in an object being inherited. Whilst the CLR can handle this, it's a design decision made by the .NET team over at Microsoft to not support it in their languages, though it seems that this is one they're looking at changing.

OK. So we can't define a static method, which isn't nice and elegant - but surely we can drop the static constraint and use the above code? Well, err... perhaps

In .NET, the CLR transparently sends an object reference to every method call made. The obvious exceptions are calls to a constructor when instantiating a new method, and calls to static methods. So it's imperative in the case above that we can always instantiate the object before we call the ImplementsMessage method.

This seems well and good, until you realise that .NET does not guarantee a default constructor as used in the example above. No, really - it doesn't. This might sound contradictory to some people, as the C# compiler will automatically create one for you if you use it on a fully qualified type at compile-time, but not at runtime.

That means the above sample will only work in the case you have explicitly defined a sane default constructor on your class at compile time. This is bad because we can't enforce this implementation with inheritance - so we're in the same problem as before: programming by convention rather than contract.

Fortunately there's a solution, and it's nowhere near as long winded as the explanation up until now. I cheekily hinted at it at the start of the article, and the answer is Custom Attributes.

Attributes are metadata you can attach to structural objects in .NET assemblies that can be reflected at runtime. If you're doing .NET, you've used them without realising. They're used heavily by components to provide information for the Visual Studio designer, are used to assign versioning and copyright information to the final assembly files as well as many other places within the framework.

By creating a custom attribute class, you can mark your classes, structs, enumerations and the like with strongly typed data that is available at runtime. This sounds like an excellent solution to the problem at hand! Here's the custom attribute class I wrote along with the updated code fragment to register these types at runtime:

[AttributeUsage(AttributeTargets.Class,AllowMultiple= true,Inherited=false)]
public sealed class HandlesMessage : Attribute
{
    readonly MessageType msgType;

    public HandlesMessage( MessageType inType )
    {
        this.msgType = inType;
    }

    public MessageType HandledType
    {
        get
        {
            return this.msgType;
        }
    }
}
foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
{
    foreach (Type type in assembly.GetTypes())
    {
        if( type.IsSubclassOf( typeof(MessageBase) ) )
        {
            // Look for the attribute saying what message they handle
            foreach (Attribute attr in type.GetCustomAttributes(false))
            {
                if (attr.GetType().Equals(typeof(HandlesMessage)))
                {
                    HandlesMessage hAttr = (HandlesMessage)attr;
                    _messageHandlers.Add(hAttr.HandledType, type);
                    break;
                }
            }
        }
    }
}
And here's a message handler being tagged:
[HandlesMessage(MessageType.InterfaceConfiguration)]
public class InterfaceConfigurationMessage : MessageBase
{
    // ...
}

And there you have it! It's a different paradigm, but still enforces the message to implement to the MessageBase contract as well as having to "register" to be picked up at runtime.

The message class itself will have to implement a few interface methods from IMessage to construct new objects, so in this case it's arguable that that might be just as valid a solution - but that has its own caveats.

For now, it's an elegant and simple way of registering message handlers in the application without relying on convention to ensure the message handler will behave as expected - and I've already had another opportunity to use custom attributes at my work to maintain backwards compatibility with some code that is being backported.

That's all for now - a more general update to come and no doubt some more C# and .NET examples too, as well as some iOS related items.

Encrypting Casper Persistence

After finally getting a basic, but not-so-straightforward usb key running with the Ubuntu livecd environment (read more here), the next step was to set up encryption on the persistence partition.

This is actually pretty straightforward, given that modernish distributions have inbuilt LUKS support which lets you (amongst other things), easily access encrypted devices.

First thing is first, we'll use the partition on the usb key to create an empty encrypted partition. Because we want to specifically set the partition label, we can't use the helpful luksformat script, instead we take three easy steps:

Create the encrypted block store:
cryptsetup create NAME /dev/sdXN

Open the block store
cryptsetup luksOpen NAME /dev/sdXN

Create filesystem
mkfs -L casper-rw /dev/mapper/NAME

All done! Well, almost. Because the filesystem label lives inside of the encrypted block store - the LiveCD isn't gong to try to mount it or unlock it, and because the casper scripts only use partitions it can see - we won't have a very happy livecd.

Time to poke around in the initrd image, which is where all the boot magic happens. Fortunately I've already done the hard work for you

A few of the other people recommending

scripts/casper-premount/99billy_mount

#!/bin/sh

BILLY_UUID="ef3adcee-b365-4473-91ae-ec9435646700"
BILLY_PROMPT="What is the ground-to-air speed of an unladen swallow?"
BILLY_ID="failboat"

# Make sure we don't do anything if its already unlocked
DUMMY=`cryptsetup status $BILLY_ID`
if [ -z "$?" ]; then
exit 0;
fi

# If we're running under Plymouth, use that to ask
if [ -x /bin/plymouth ] && plymouth --ping; then
PWD=`plymouth ask-for-password --prompt="$BILLY_PROMPT"`
echo $PWD | cryptsetup luksOpen /dev/disk/by-uuid/$BILLY_UUID $BILLY_ID
while [ $? -ne 0 ]; do
PWD=`plymouth ask-for-password --prompt="$BILLY_PROMPT"`
echo $PWD | cryptsetup luksOpen /dev/disk/by-uuid/$BILLY_UUID $BILLY_ID
done
else
cryptsetup luksOpen /dev/disk/by-uuid/$BILLY_UUID $BILLY_ID
fi

scripts/casper-premount/ORDER

/scripts/casper-premount/99billy_mount
[ -e /conf/param.conf ] && . /conf/param.conf

MSN display name fix for win32 Pidgin

For the last week or so, I've been annoyed by changes Microsoft have made to servers causing your MSN display name to get reset each time you log in. The behaviour affects genuine and other MSN clients, and there's no sign of it being fixed any time soon.

So in the meantime I've built a Pidgin 2.6.3.0 set of win32 binary with retrospectacus's contributed patch which gets around the problem (for now). I've put them up with this post in case anyone else is interested.

If you're curious or would like to build your own version, the bug report is here:
http://developer.pidgin.im/ticket/10763

Happy MSNing :)

UPDATE With the 2.6.4 release of Pidgin, I've removed the download links to my build of Pidgin.

Pages

Subscribe to RSS - syndicate