How can I use non-Silverlight assemblies in a Silv

2019-01-18 04:50发布

问题:

I'm working an project (pure hobby, "Sharping my skills") which has one unified back-end and multiple front-ends (ASP.NET MVC 1.0/JQuery and Silverlight 2). When I try to add reference to my business layer assembly in the Silverlight 2 project (VS2008); It gets rejected, because it's not a Silverlight assembly.

Is their a way to include and reference a non-Silverlight assembly in a Silverlight app?

回答1:

No there is not. Silverlight runs on a completely different CLR which is incompatible with the normal (desktop) CLR. It has an underlying different set of APIs in the BCL and most importantly a different metadata version number. These two factors, among others, prevent assemblies compiled for the desktop CLR from running by default on the Silverlight CLR.

All assemblies must be compiled specifically for silverlight.



回答2:

Actually, whilst it is difficult and probably not a good idea, it is possible to reference CLR assemblies in a Silverlight project. David Betz has an example on his blog: http://www.netfxharmonics.com/2008/12/Reusing-NET-Assemblies-in-Silverlight

Again it's worth stressing that you probably don't really want to do this. The Silverlight framework has been developed by experienced engineers, who have put a lot of thought into what should be included and what shouldn't. Think about the CLR objects you think you need, and try to understand why they aren't currently available, and what the alternatives are.

Finally, remember that any CLR objects that you do add, will increase the size of your download.



回答3:

No it't not possible to reference assemblies that are not built against the Silverlight runtime.

The way I have gotten around it is to create a new project for my business assemblies and then add all the classes from the original assembly to it. The key is that when you add them do it as an existing item and on the Add button click the down arrow and Add as Link. That way you still only have a single code base although you may have to add a few classes such as ApplicationException to make up for things missing from the Silverlight runtime.



回答4:

The short answer is no, I'm afraid. The Silverlight runtime was designed to be a subset of the .NET framework, but the two are not directly compatible. (The runtimes are implemented quite differently, I believe, as Silverlight was designed to be cross-platform.)

The good news however is that you have a whole host of workarounds. This blog post and this CodeProject article discuss the issue in depth and offer a variety of clean solutions. Hope that helps...



回答5:

No. The source csproj must know it is a Silverlight project. This may mean keeping two project files with the same source ".cs" files. There is a handy csproj trick here - (copied from protobuf-net where I do this for multiple frameworks):

<ItemGroup>
    <Compile Include="..\YourMainProject\**\*.cs" />
</ItemGroup>

Then you only have to maintain one project; the Silverlight project gets everything from the tree.

Note that the Silverlight BCL is heavily restricted, and not all functionality will be available. Getting code that compiles on both regular .NET and Silverlight can be... challenging.

Alternatively, use proxy classes in the Silverlight app (i.e. via WCF etc). Not as rich, but simple to do.



回答6:

A word of warning, my experience on this comes from developing for Windows Phone 7, so this might be subtly different from normal Silverlight 3.

JaredPar has pointed out the Silverlight CLR is incompatible with normal CLR. This is not 100% correct as assemblies compiled as Windows libraries will still work under silverlight assuming that they use supported APIs. You can manually edit the silverlight project and add a reference to the normal .NET assembly. Note that you can only add a reference to a compiled assembly and not the project.

The silverlight app will compile and run, but as soon as it tries to use a class that is not present in Silverlight, you get a run-time error.

To demonstrate the difference in APIs, have a look at following screenshots. As you can see the two assemblies have some common APIs, but the Silverlight one has a few missing. As soon as your assembly tries to hit those API the app goes BOOM!

Full .NET 4.0 mscorlib (System.serialization namespace):

Full .NET 4.0 mscorlib http://img188.imageshack.us/img188/2131/fullmscorlib.png

Silverlight 3 mscorlib (System.serialization namespace):

Silverlight 3 mscorlib http://img526.imageshack.us/img526/4254/sl3mscorlib.png

The disadvantage of linking a full .NET assembly is that you wouldn't know until runtime which APIs are not supported. Considering that potentially some supported system API can use unsupported system API, there is no easy way to work this out ahead of time.

There are things you can do to make parallel development easier. The approach recommended by Microsoft is to have separate project for .NET and Silverlight that share the same source code. You can do it manually by adding files as links to the project. It's a bit of a maintenance nightmare, but at least most errors will be caught at compile time.

So now when you compile something that references API missing in Silverlight you get an error:

public class SerializableExample: IEquatable<string>, System.Runtime.Serialization.ISerializable
{
}

error CS0234: The type or namespace name 'ISerializable' does not exist in the namespace 'System.Runtime.Serialization' (are you missing an assembly reference?)

With help of conditional compilation (a-la good ol' C/C++ days) you can disable stuff that is not supported:

public class SerializableExample: IEquatable<string>
#if !SILVERLIGHT
  , System.Runtime.Serialization.ISerializable
#endif
{
}

Microsoft also provide a Project linker tool that allows for automatic maintenance of projects that have linked files. Unfortunately the current release does not run on VS2010, you can probably compile the source and make it happen, but I haven't tried.

http://msdn.microsoft.com/en-us/library/dd458870.aspx

Direct download link:

http://download.microsoft.com/download/6/3/8/6382E28D-2EBD-4A4E-BB76-6F425E1C9DB9/MicrosoftPracticesProjectLinkerFeb2009.msi

This Microsoft page describes mult-targeting in excruciating detail.



回答7:

The Silverlight runtime is a subset of the main .Net CLR. Although this can seem to be a pain there is a sensible reason for it - the Silverlight runtime needs to be light enough to be a browser plugin.

If you place your other classes behind webservices then they can run under the full .Net runtime while your Silverlight application runs under the cut down CLR in the Browser plugin.



回答8:

Have you tried this? It can build Silverlight Assembly directly by right clicking the .NET library project.

http://buildassilverlight.codeplex.com/



回答9:

Late to answer, but adding this link to assembly-level vs. file-level reuse. It's very thorough.