Windows Phone 7 Environment.DeviceType = Un-Blendable code

So, you’ve decided to be really inventive and build some helper classes that work around the limitations of the Windows Phone 7 emulator (eg inability to simulate network connectivity, accelerometer, location, actually anything that isn’t in Silverlgiht for the desktop). Of course you don’t want this code to be used when the application runs on a real device so you have some code that looks like:

if (System.Environment.DeviceType == DeviceType.Device)
{
    // Device code
}
else
{
    // Emulator code
}

This compiles and runs fine when working in Visual Studio and Blend. However, if this code is invoked as part of building the UI to be displayed in the designer (remember that both Visual Studio and Blend run a bit of code in the background to make sure things are created properly and that data contexts are created to facilitate data binding), you will likely see a message similar to the following.

image

“Method not found: ‘System.DeviceType System.Environment.get_DeviceType()’.

Right, you think, simple enough to fix, I just need to wrap this in a check to see whether it’s running in the designer or not:

if (!DesignerProperties.IsInDesignTool && System.Environment.DeviceType == DeviceType.Device)
{
    // Device code
}
else
{
    // Emulator code
}

Unfortunately you’d be horrified to note that this does NOT get the error to disappear. The error is actually an error raised by the JIT compiler when it goes off looking for DeviceType property. Unfortunately there is no such property on the desktop so it throws an error. Typically JIT compilation is done on an “as required” and “method-level” basis which means that the whole method you are working in will be JITted together, resulting in the error even if the code will never be executed. The workaround…. just move the erroneous  code to a method that won’t get JITted:

 if (!DesignerProperties.IsInDesignTool )
{
    DoRuntimeCode();
}
else
{
    // Designer code
}

private static void DoRuntimeCode()
{
    if (System.Environment.DeviceType == DeviceType.Device)
    {
        // Device code
    }
    else
    {
        // Emulator code
    }
}

Problem fixed…. happy coding.

(FWIW this is a trick that Windows Mobile developers have used for years to build libraries that work across both .NET Framework and .NET Compact Framework where there are features on either platform that aren’t available on the other)

Leave a comment