Converting Tempest to run on WinRT: Part 1

First, a short introduction to Tempest. I had avoided posting about this project in the past because I wanted the first post to be a quick tutorial and announcement of a beta. However, this is a perfect opportunity to really dive into some of the lower level APIs of WinRT and share the experience.

Tempest is designed to be a simple application protocol messaging library that works everywhere. This is to say that it gives you a simple way to define messages and lets you select how these messages are transported. Furthermore, the library is built to work on .NET 3.5, .NET 4, Mono 2.10, Silverlight 4 and Windows Phone 7.? “Mango”. Though, at this point in time, I’d consider Tempest to be an early alpha for .NET and Mono. Silverlight and Windows Phone 7 support compiles, but assuredly does not work yet.

Getting it to compile

For Part 1 we’ll talk about even getting Tempest to compile. Keep in mind that the vast majority of the code must still work on standard .NET, so converting over to WinRT APIs completely isn’t an option. To support the various platforms, there’s a number of compiler defines already present in Tempest:

  • SAFE – Disables any unsafe optimizations (unsafe, System.Reflection.Emit)
  • NET_4 – Enables .NET 4 specific code. This is mostly optimizations from System.Collections.Concurrent and using SpinWait, but does include one very useful API based on Task.
  • SILVERLIGHT
  • WINDOWS_PHONE

WinRT does not contain System.Reflection.Emit, so first I turned SAFE on. Type.IsValueType, which is used primarily in MutableLookup`2 from Cadenza, has been moved to TypeInfo. For a quick fix, I replaced the check for it with:

if (default(TKey) == null)

Simple enough change, but the error list at this point is still quite daunting. Here’s a short list of what was affecting me:

Networking

As you might imagine, for a networking library, the first is a huge blow. As WinRT has its own implementation of sockets, I’ll have to write a new transport provider. Fortunately Tempest is designed to be able to do this, so for the moment I’ll just remove the existing network implementation altogether.

Unfortunately that wasn’t the only usages I had, as System.Net.EndPoint was used throughout my contracts for connection targets. So either I can write WinRT only implementations of EndPoint, or I can write my own type and take control. I opted to write my own types (prototype design): ConnectionTarget, DnsConnectionTarget, IPConnectionTarget.

Reflection

When I was working on this last night, I was under the impression that Type had simply been gutted. Today I know that many of the members I had been using were moved to TypeInfo. There is an extension method in System.Reflection on Type called GetTypeInfo() that will get you the TypeInfo instance. In order to facilitate code compatibility with normal .NET, I added my own little extension:

#if !WINRT
public static Type GetTypeInfo (this Type type)
{
	return type;
}
#endif

Using this, I can just call .GetTypeInfo() on my type instances in either framework and all should be well. It’s not terribly efficient as I can’t store instances to the proper type easily/cleanly most of the time, but it gets the ball rolling.

Despite TypeInfo containing most of what was originally on Type a few things are still missing, such as .GetMembers(). I was instead able to use TypeInfo.DeclaredProperties and its friends with LINQ to get to the members I wanted, including filtering I was originally doing in LINQ after GetMembers().

Serialization

To be perfectly honest, where most of the reflection used and all of .NET’s built in serialization is, is in a custom automatic serialization system. This is probably the buggiest and worst designed aspect of Tempest. Last night I made the decision that for WinRT (thinking at the time reflection was gutted), I’d only support Tempest’s ISerializable and ISerializer<T> interfaces. For now I’m going to leave that restriction in place until I can get it sorted out.

While System.Runtime.Serialization is present with DataContractAttribute and friends, SerializableAttribute and System.Runtime.Serialization.Formatters.* are not. These portions of code were optional and already disabled for Silverlight, so I just added the WINRT flag to the check.

Miscellaneous

The types using System.Buffer weren’t used anywhere except for the existing networking implementation, so I simply removed them from the WinRT build for now. Having gotten things to compile at this point, I decided to see what would happen if I turned on NET_4, and to my surprise everything compiled as is. It appears that WinRT’s support of the baser types (like collections) is quite good. Where things start talking to the OS (Sockets) is where things start to get replaced, and old crufty systems (SerializableAttribute) seem to have been trimmed out.

Now that I have the basic system compiling, I need to implement a transport using Windows.Networking.Sockets, which will be Part 2.

This entry was posted in Projects, WinRT and tagged , , . Bookmark the permalink.

2 Responses to Converting Tempest to run on WinRT: Part 1

  1. Pingback: Introducing the Xamarin Mobile API Preview | Code Monkey vs. The World

  2. What will help the ecosystem is allowing WinRT apps to run in windows on the desktop.

Add Comment Register



Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>