Sharing Silverlight Assemblies with .NET Apps
At the recent PDC, Scott Guthrie announced in his Silverlight 4 keynote that we had implemented a new feature, to enable developers to share certain assemblies between Silverlight and .NET. There are many differences between Silverlight and full .NET including WPF, and this new feature doesn’t solve those differences – in those cases, you’ll still need to compile your code twice. But in some cases, developers will write code that only uses features whose behavior is identical between Silverlight and full .NET, and in those cases, we want to enable that code to be shared. This post provides more detail on that sharing, and explains how developers can target it, and what the restrictions are.
Today, many developers write code that is intended to run on both Silverlight and .NET. A good example would be validation code: when writing a client-server application, you want to validate the data at the client (to make sure the user gets quick feedback) and then re-validate it again at the server (to make sure a rogue client implementation can’t send back bad data.) Today, in order to get that scenario to work, developers need to compile their source for Silverlight and also for .NET. In addition to dual-compilation, developers need to manage and deploy those assemblies separately, ensuring that they end up being deployed to the right places and consumed by the right platform (Silverlight or .NET). Today’s model is certainly workable, but it is not ideal.
We’ve heard from many developers that you want something better. We’ve also read quite a number of blog and forum posts stating the same. We’ve even seen some interesting workarounds to try and make the situation better for themselves and other developers. Cool! Specifically, developers want to write and compile their code once and deploy it as part of both their Silverlight and .NET apps, without having to dual-compile or worry about paying attention to the compilation target. This ability has the obvious benefit of avoiding duplication of effort for a number of the steps in your development and deployment processes.
We named this new feature “assembly portability”, given that the feature allows your code to be “ported” between both Silverlight and .NET. Portability provides the ability to compile your source with the Silverlight tools, and run your built assemblies on both the Silverlight and .NET runtimes. This feature doesn’t change the underlying implementation of either the Silverlight or .NET runtimes; instead, if you write code that only uses APIs that have the same behavior across Silverlight and .NET, it allows you to use one set of binaries to target both. But how do you know if the APIs you are using are compatible? We have identified five key assemblies that are compatible between Silverlight and .NET. (The Silverlight UI layer is of course not one of these – there are some important differences between Silverlight UI and WPF.)
Like most features we build, we had a lot of choice about how to design the feature, and which scenarios we would enable. At the heart of the feature, a major design choice was to enable portability from Silverlight to .NET. The motivation for this choice was that Silverlight exposes an API subset of .NET, and so assemblies built with Silverlight should “just work” on .NET, whereas the reverse direction (.NET assemblies running on Silverlight) would have proven more technically challenging (for us all).
Another important design choice was identifying the set of Silverlight/.NET assemblies that developers could safely use, while still maintaining binary comparability. We looked at the scenarios that would both most benefit from portability, and would be straightforward for developers to use. We looked at a bunch of scenarios, including: the most low-level, typical business logic, networking and also UI. We decided we would start with the most fundamental and requested scenarios for this release. As a result, for .NET 4 and SL4, we have enabled portability for a significant set of low-level assemblies that we believe will enable a variety of interesting scenarios.
For SL 4 and .NET 4, we have made the following assemblies portable:
Note again that the Silverlight surface area for these assemblies is what we made portable. There are a great number of types and members in the .NET surface area that cannot run on Silverlight. As a result, you need to write code that targets the Silverlight versions of these assemblies in order to get this scenario to work.
Also note that there may be some behaviors that are not strictly identical across both platforms. We’ve worked to avoid those behaviors, however, those differences are sometimes very subtle and difficult to identify. Please do contact us if you do see behavioral differences between Silverlight and .NET, for portable APIs, which are bothering you.
Visual Studio Experience
Like all .NET features, it is important that we provide good tooling support in Visual Studio. This feature can be used in Visual Studio, in just the way that one might imagine. Developers should write their portable logic in Silverlight Class Library projects, and then are free to reference such projects from both Silverlight and .NET application projects. To clarify, on the .NET side, you can reference such a library from any kind of .NET project (Ex: WPF, winforms, WCF, WF, ASP.NET, …).
The only caveat is that the support in Visual Studio was implemented in such a way that you need to click a few extra times to get a reference to a portable project correct setup. For VS 2010, you must rely on browsing to the binary – AKA “binary reference” – that is built from the Silverlight class library to setup a reference. You cannot just reference the project itself – AKA “project to project reference”. Note that this restriction only exists for .NET apps, and not Silverlight ones.
The following are the basic steps to follow to enable the use of portable code in Visual Studio 2010, followed by a set of screen caps that hopefully make it super clear what to do.
- Setup projects
- Create .NET application
- Create or add existing Silverlight class library project
- Build Silverlight project
- Establish portable code reference
- Reference Silverlight class library binary from the .NET project
- Run App!
Step 1 – Setup projects
Step 2 — Establish portable code reference to the other project (required going up and back down the directory structure to the Silverlight library project).
Step 3 – Code
Step 4 – Run App!
Note: My app is a WPF app that is intended to display how many days there are until the Vancouver 2010 Olympics start, from today. The Silverlight library is the one that does the actual countdown calculation, and is (naturally) usable in both .NET and Silverlight apps. Cool!
Looking Forward and Feedback
It is great to see so much energy around both .NET and Silverlight, and particularly around the maximal sharing of code across the platforms. I encourage you to use this new scenario to its fullest extent, and to communicate back to us where you’d like to see the feature expanded in the future.
We are aware of some scenarios that are not currently enabled to be portable, but that developers will probably run up against pretty quickly. The most obvious ones are XML, networking, calling WCF web-services and UI code. Another interesting one is portable XAML. It would be really useful to hear from you on the specific scenarios that you would like to implement in portable code, but cannot implement due to the limitations that I’ve mentioned. I’d also like to hear why you saw being able to implement that scenario in portable code as being such a benefit. Your feedback will help guide us with future changes in the portable code space.