XNA to MonoGame – Windows 8 Porting

I’ve been meaning to start writing about my experiences porting Space Salvager from XNA to MonoGame, but as is often the case things keep getting in the way – but not tonight!  These are a few issues I found porting from .NET 4.0 to .NET 4.5 Portable, these are not strictly MonoGame but are a part of going from XNA 4.0 to MonoGame for Windows 8.

Type.IsSubClassOf(Type)

This member function is used to check if a class type inherits from another, useful if you want to get all the objects of a certain type and their subclasses from a scene.  More often than not is would be used, for example:

if (obj is GameObject)

This would return true if obj is or inherits from the type GameObject – this works for both classes and interfaces.  However, it is not always possible to do this and so Type.IsSubClassOf(Type) must be used, such as below:

foreach (GameObject obj in objects)
{
    if (obj.GetType() == type || obj.GetType().IsSubClassOf(type))
    {
        yield return obj;
    }
}

In .NET 4.5 Portable this method is no longer available, however it can be replaced with TypeInfo.IsAssignableFrom(TypeInfo) found in System.Reflection.  If we apply this change to the above example we end up with:

foreach (GameObject obj in objects)
{
    if (obj.GetType() == type || type.GetTypeInfo().IsAssignableFrom(obj.GetTypeInfo()))
    {
        yield return obj;
    }
}

For ease of use it’s advisable to wrap this inside a function somewhere, this makes using both versions for multiple platforms much easier as well:

public static bool CheckTypeIsSubClassOf(Type super, Type sub)
{
#if WINDOWS8
    return super == sub || super.GetTypeInfo().IsAssignableFrom(sub.GetTypeInfo());
#else
    return sub == super || sub.IsSubclassOf(super);
#endif
}

StreamReader

.NET 4.5 saw the move to all API calls with an average execution time of over 50ms , which is yet another annoying change for developers moving to Windows 8; that being said it is good practice to run certain processes on a separate thread from the UI thread.  This can be become problematic later on when you have to run certain processes on the UI thread, but that’s something I’ll cover in a later post.

One of the commonly used API calls moved to asynchronous execution is System.IO.StreamReader, which can no longer be created by simply calling its constructor.  The solution I chose to implement was essentially a work-around the asynchronous nature of the call and force the current thread to wait for task to return.  I chose to do this for reasons:

  1. Streams were already being created asynchronously in Space Salvager.
  2. These new asynchronous functions are not available in .NET 4.0 and therefore was not cross-platform compatible
public static StreamReader GetCurrentLocationStream(string filepath)
{
#if WINDOWS8
    /* Get the current storage folder */
    Windows.Storage.StorageFolder folder = Windows.ApplicationModel.Package.Current.InstalledLocation;

    /* Wait on the task to complete */
    System.Threading.Tasks.Task task = folder.OpenStreamForReadAsync(filepath);
    task.Wait();

    /* Return the result as a stream reader */
    return new StreamReader(task.Result);
#else
    return new StreamReader(filepath, System.Text.Encoding.UTF8);
#endif
}

Above is the solution that Space Salvager uses, both versions of the function will return the StreamReader synchronously.

string.Contains(char)

This is barely worth mentioning as it’s such a small issue, however it does perplex me why it was removed. string.Contains(char) was removed in .NET 4.5 Portable, however the solution is very simple. call char.ToString() to convert it to a string.  Easy, but still odd that it was removed.

Thread

There are a two major changes for System.Threading that I came across whilst porting.

First off the Thread class has been removed, however the Task class behaves almost identical except there is no Task.Sleep(int) function.  There may be another way to sleep a Task, however there isn’t one that I’ve found.

System.Threading.Tasks.Task start = new System.Threading.Tasks.Task(delegate { /* Task */ });

Second there’s no longer a System.Threading.ThreadPool: now this was a major issue for Space Salvager as it runs a lot of processes in the background that don’t need to be completed straight away, but do take quite a long time to run and have a tendency of fighting each other for resources if you just spawn them all as Threads/Tasks and walk away.  The solution I chose was to implement my own ThreadPool, but that’s something I’ll cover in a later post as it’s quite a lot of code and deserves it’s own post.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s