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.
The most important one for us would be congruency/compatibility between the WCF stacks on the client side(System.ServiceModel and System.Runtime.Serialization). Right now, you can't even share Contract assemblies without a recompile or managing different code bases. Additionally, the WCF channel stack and configuration of WCF is crippled in WCF. This makes it hard/impossible for us support customizations that we hook into the WCF extensibility layer.
I would also see XML processing to be a key scenario where congruency is very important.
Please feel free to contact me for discussion:
scott underscore prugh at csgsystems.com
I support it should be only one runtime w/ muiltiple profiles. If I remember correctly Java needs just one JRE.
I would resequence my preference based on mepfuso's comments above. Ideally, we would have one runtime with differing profiles. It seems silly to have multiple.
In lieu of that(and in the interim) my comments above hold:
Justin Angel: The behavior you are seeing is that mscorlib is always considered 'portable'. Due to the way that the runtime is architectured, there can only ever be one mscorlib loaded in a given .NET host. The above difference between the scenario you pointed out in your blog post and above, is that this is now supported and we've added a few more assemblies to the list.
I'm going to chime in on the huge dissappointment as well.
We need UI compatibility as well!
With only those few core assemblies supported, this is pretty much useless.
@eggman -- System.Cryptography is part of mscorlib.dll, which is in the list. Try it out; it should just work!
@JustinAngel -- I agree with David. This scenario has always worked for mscorlib types; we just chose not to advertise that. Smart folks like you were able to figure this one out early ;)
@All -- This is great feedback that we'll take into future release planning. I don't see us being able to make substantive changes to .NET 4 RTM at this point.
Huge disappointment to me. We were told in PDC 2007 that if you write 100% managed code your code will run in Silverlight. That has never been the case. Silverlight is a FRAGMENTATION of the .Net framework. Call it something different. It is NOT .Net. It is not even a subset you can target in Visual Studio. You can't have a single project that outputs a .Net 4 dll, a Silverlight DLL, and a .Net 2 dll. There is no way to do this.
If a company is going to have to make an entirely new SKU for Silverlight then it will hurt adoption.
Writing for .Net should mean writing for .Net. Not "Oh, which version of the client profile or in browser / out of browser runtime did you actually mean?".
One of the bits that I commonly share are the Service and DataContracts, however System.ServiceModel isn't portable.
Also some of my assemblies inclyde Dynamic, which again isn't portable since it's in the CSharp assembly.
I'm going back to linking files. I don't see a big point in having this assembly sharing if only a really limited set of assemblies is exposed and quite often we need something outside of those 4.
Also if I've to use links for some of my code and assembly sharing for others, my solution becomes inconsistent which means that I can't even use file sharing for those few helper classes that coudl actually be shared.
If you made more assemblies portable it would be great and that would allow us to actually take advantage of this feature.
Another 'advantage' that I was thinking about linking files or recompiling for Silverlight is that we can have different versions of the code using compiler conditions (the ugly #if !SILVERLIGHT). A lot of Open Source projects are doing this. They provide a different implementation for the Desktop that is slightly more efficient because it uses features available for the full framework.
For example, Ninject works well on Silverlight, but some features are only available on the desktop version due to some SL limitations (like lack of private refleciton). Nothing wrong with this, my point is that when building a framework, sharing assemblies isn't an option since we don't want to punish desktop customers just to make it compatible for Silverlight, and the other option is actually not that hard.
I think I'll stay with "portable" source code instead of "portable" assemblies.
This is definitely a good step in the right direction but it doesn't go far enough. As they correctly point out in the article, we certainly don't want to duplicate the business logic in the UI and the Business/Service Layer. To achieve this, I would say we need the following to be "portable" assemblies...
5) Any other assembly that addresses cross cutting concerns.
Here are couple of ideas to think about..
1) Instead of retrofitting the existing assemblies into making them "portable" assemblies, how about refactoring the types into the portable assemblies i.e., create new assemblies?
2) Extending on the previous idea, .net runtime should have a notion of "dynamic assemblies" that I can compose based on the existing types in other assemblies. I should be able to pick and choose the types that I need from the Framework and then build assemblies based on that.
Having previously been working with WPF/WCF and creating solutions which benefited from shared assemblies: I'm inclined to agree with a couple of the posters above.
The assemblies that would have already been of great use to me are as listed by RK.
System.ServiceModel, System.Runtime.Serialization, System.ComponentModel.DataAnnotations, System.Xml
I'm in VS 2010 and I'm trying to take advantage of this feature. However, I've run into a problem.
If the "portable" assembly is GAC'd on the development machine, it doesn't get packaged into the .xap file by VS. This is a problem because the client machines won't have this assembly when they attempt to run their silverlight app.
Is there a workaround to getting the portable assembly packaged into the .xap, if the same assembly is GAC'd on the machine?
Ive been waiting for something like this for a while. For me, it appears to not quite go far enough. My needs are simple, I dont need the user interface to work across both silverlight and wpf, but I don need the business logic and data access (through wcf) to be able to work in a simple console application. As a simple example, I may want to be able to write a simple test of my code without having to host in a full blown silverlight app. But I desperately need System.ServiceModel to be ported and work from the Console. I REALLY hope it goes into a future release.
I haven't tried it yet, but would it be possible to share XAML and UI logic between SL and .NET/WPF, and what would have to do?
Well done but that needs to be pushed further.
WCF serialization capabilities in Silverlight needs to be as good as .Net.
I am really disappointed about project references not being fully supported. How are we supposed to build large apps with multiples build config without project references? I think we will stick to our way of doing things, which is built around Csla.Net and Csla.Light and source files linking between SL and .Net class library projects. After a bit of work with CodeSmith, you can link those files automatically in the SL project. And if you hate #if !SILVERLIGHT then use partial classes to write common code, client-only code and server-only code.
BTW, I highly recommend Csla to enable you to share all business logic between client and server fluidly and more importantly, WITHOUT needing System.ServiceModel at all on the client. If you do your homework, you will discover a whole world of possibilities!
As for System.Runtime.Serialization, Csla does offer a way of handling serialization between the client and the server but at the cost of writing some extra code, which we automated since it is always the same.
If you need some more details, drop me a note at edore at stavibel.qc.ca