A first hand look from the .NET engineering teams
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.
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.
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!
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.
I have to say that on the surface this is a huge disappointment. I always found myself wanting to create a "master" assembly in .NET and consume it in Silverlight (and other applications), not the other way around.
Silverlight always feels like it's a bit on the "fringe" of the .NET world and unfortunately this doesn't do anything to correct that.
I remember when Silverlight 2 came out - I thought "wow, it uses the CLR!" only to realize it didn't really and none of my code was portable.
I had the same experience reading about the PDC announcement. "Finally! Now I can use my .NET Assemblies in Silverlight!" only to find out that, again, I can't.
Huge disappointment, at least for me :(
ShadowChaser: if it worked the way you suggest, how would you avoid calling methods that are not available in Silverlight (for example: Enum.Format)? Or did you think MS would implement every type and member in .NET?
ShadowChaser: I'd love to hear more about what you think is missing from Silverlight. What things from .NET do you find you need that you can't use in Silverlight? Feel free to contact me davidDOTkeanATmicrosoft.com.
I do hope the final version of VS2010 will provide support for referencing projects, because binary references are very brittle: no build integration (automatic recompile etc.), totally ignores the configuration manager (Debug/Release builds), and I doubt debugging & edit&continue will work properly.
Sure, you can hack the MSBuild files, but simply allowing references to the Silverlight projects would be much simpler.
I suspect that I will find System.XML to be a must have. With data objects usually being stored and transported in XML format, we need it to create data objects that can serialize and deserialize themselves using whatever format our counter-parties at other companies demand.
While this post opens up the possibility of sharing middle-layer code between WPF and Silverlight applications, it's very disappointing how hard it is to write your UI in Silverlight and use the same code to generate a WPF application. There's many differences in how the UI works between WPF and Silverlight, and it's not just a matter of making two projects and sharing code files; some conditional compilation must be involved and occasionally we've had to implement types ourselves.
Wake me up when I can write a non-trivial UI in SL and move the XAML/code-behind to a WPF project and have it work with no tweaks. I'm not fully involved with our project, but I hear constant curses from the people that are.
How is this different from the existing DLL sharing abilities that were in since Silverlight 2 + .Net 3.5 SP1?
-- Justin Angel
@Justin Angel: just what I was about to ask.
Before reading the article I was excited that it would at least fix the current versioning and serialization issues for WCF between desktop and SL, but alas it doesn't look like it (haven't tried this yet).
IMHO the most annoying lake is that some foundations of WPF aren't currently implemented within SL3, and even SL4 : eg., it's very disappointing that the Routed Event API isn't public in SL (as it may be existing, for some controls are triggering Routed Event). This prevents the developper to share code between a WPF component and a Silverlight component.
And that the same thing for RoutedCommands. But I admit that the core differences are being reduced, e.g the implementation of the Binding functionnality in DependencyObject instead of FrameworkElement in SL4.
the only part of .net I have needed to share between silverlight 3 and .net 3.5 is System.Security.Cryptography;
and its not in the list :(
Hi, I am developing a silverlight application based on WCF Rias servics and was having trouble with resource sharing between web project and silverlight project. This new feature came to the rescue as I isolated the common resources into a dedicated silverlight class library, which is shared by both UI and web based ria services. It works! GREAT!!!
Now, the little glitch, which is seems to be nothing more than a little annoyance. If at the web project, I add the reference to the SL assembly, everything shows up fine. If instead, I add the reference as a project reference, everything still keeps on working fine, but Visual Studio complains about that reference by showing the typical yellow yield sign next to it. Oddly enough the reference ends working as expected, which is good.
Could you just correct that VS glitch?
Overall, great work, guys!!!!
I also blogged about this great feature here:
Assembly portability is great! But I feel something is still missing, such as to access SQL compact and Sync framework.
In the elevated/trusted applications we could call COM objects through dynamc object. Can we use dynamic object in SL4 to call into .NET 4 assemblies?
I would second the request that project references be made to work. Without that, the feature is difficult to use at best .
In my opinion, the whole extra-silverlight-runtime thing shall be discarded, it shall all be the same runtime and the .NET profile concept shall just be expanded:
- Common base profile == Silverlight browser plug-in == sandboxed, minimal client assemblies, ~5 mb download on windows machines, maybe ~20 mb on other systems
- Base Desktop profile == Silverlight Out-Of-Browser == out-of-sandbox-by-permission, ~20 mb more for most required System assemblies
- Client profile, ~150 mb (heck, that's a lot already anyhow in .NET 4.0)
- Server profile, ~300 mb
- Maybe some Enterprise profile (w/ office, sharepoint, blah), ~95943579438393 mb and lots of $$$ for obscure features that the microsoft marketeers may charge from those big companies who don't know what to do with their money anyway
I don't see why this shouldn't be possible if the .NET library was architectured properly. The code that goes to the "meat" of the hosting OS and its security aspects should be held in one place so that the standard .NET library around it could just call in (like Silverlight does with all those cryptic XcpImport methods) while the API remains the same regardless if it's running on windows desktop, as a silverlight browser plug-in or a C64.