(Note: I typically don’t tweet my blog posts, but I did so with this one as I want to make sure those following the developments at MIX10 around Windows Phone 7 and Silverlight are aware of some key differences between the platforms.)
Tuesday at MIX10 there was a big release that went completely unannounced Silverlight 3.7 is now in CTP! That’s right 3.7! I can’t believe it! It’s amazing! It’s, uh, um, hey, wait a minute, isn’t the release candidate for Silverlight 4 in the wild?
No, I’m not losing it (well maybe I am, but that’s neither here nor there). In my last post I discussed one of the key shortcomings, in my opinion, of the WP7 platform, the lack of browser support for Silverlight. I pointed this out because my fear is that a lot of people are going to assume that WP7 supports browser hosted Silverlight since native apps can be written for with Silverlight. As a result, people may not be willing to adopt the WP7 platform quickly since they can’t leverage existing Silverlight assets. The goal of this post is to try and show a couple of different ways you can reuse code across both the “browser hosted” and “phone hosted” silverlight platforms.
First we’ll set up a solution with two projects, a Windows Phone application, and a Browser Hosted (Silverlight 4) application:
Next we’ll want to add a project that will contain code we want to reuse across the the two applications. In this case we’ll choose a Silverlight class library project that targets the Silverlight 4 runtime:
Next we’ll want to our two applications projects to reference the class library. Adding a reference to the Browser Hosted application works without problem. However, when we try to add the reference to our Windows Phone project we get the following error:
Let’s try the reverse. Let’s first add a Windows Phone class library project:
Now let’s add the project references. Adding the references to the Windows Phone application works as expected, but now the Browser Hosted applications gives us ethe following error:
So, what the heck is going on here? To find out we’re going to need to take a peek at the assemblies referenced by our Browser Hosted and Windows Phone application. The assemblies for the Browser Hosted application can be found in the following directory: C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\Silverlight\v4.0. Let’s choose one assembly to look at. In this case we’ll use the System.Windows.dll. Here are the details of the assembly:
The assemblies for our Windows Phone application can be found in the following directory: C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\Silverlight\v4.0\Profile\WindowsPhone. If we take a look at the System.Windows.dll assembly in this directory we’ll see the following:
See the difference? Windows Phone uses, what is, essentially, Silverlight 3.7, which is why we can’t add a reference to a Silverlight 4 class library. If you take a look at some of other assemblies in this directory, such as System.Core.dll, you’ll see something like this:
These core assemblies are actually compiled for the .NET Compact Framework 3.7.10056.0. This is why we’re unable to add a reference to a Windows Phone assembly to our Browser Hosted project.
So, how can we share Silverlight code between our Windows Phone and Browser hosted applications? There are two approaches that initially come to my mind. (I have a third idea involving T4, but that needs to get flushed out yet). The first thing we could do is create a Silverlight 3 class library project:
All we need to do now is add the reference to our two application projects, which will work. However, I don’t like this approach as it’s least common denominator (LCD) programming. We’re actually holding the code in both applications back from full potential by using a lower version of Silverlight.
Another approach is to use linked files. In this case we’ll delete the Person.cs file from our CxAg.Shared.Phone project. We will then add the Person.cs file from the CxAg.Shared.Silverlight4 project to our CxAg.Shared.Phone project as a linked file. The result will look like this:
See that little arrow by the Person.cs file? It indicates that it isn’t actually a file, but, rather, a pointer to a file located somewhere else. In our case, it’s just a point to the Person.cs file in the CxAg.Shared.Silverlight4 project.
One thing you’ll want to keep in mind is how to handle code that compiles for one platform, but not for the other. An approach I’ve taken in similar scenarios looks something like this:
I like to declare my shared classes as partials. These allows me to include platform specific code in each project (as separate, non-linked files) without breaking the build. In my opinion neither of these solutions are ideal, but they’re workable. As I mentioned earlier, I’m working on a third, T4 based solution, but that’s still in progress. Keep in mind too that we’re working with what is, for all respective, purposes a new development platform, so there are kinks to be worked out. I hope this gets you on your way to successful Silverlight 4/Winodws Pohne 7 development!