
Introduction
This article comes to solve the issue presented by David Betz in his article Reusing .NET Assemblies in Silverlight by creating a simple Console application that can be run in the Post-Build commands.
Background
Now that Silverlight has entered its second version and is starting to be implemented by a larger number of developers, more advanced applications are being developed on the framework.
One of the powerful features of Silverlight is its connectivity with WCF Services. As most architects choose to implement the contract classes in a public assembly that is then referenced by both the Service Implementor and the Client, an issue occurs when attempting to reference this public assembly through a Silverlight application.
I won't go into too much detail as to why Visual Studio doesn't allow you to add non Silverlight assemblies to a Silverlight project since this is presented in great depth in the article posted by David Betz on his NeFX harmonics site. But, in a nutshell, the assemblies that Silverlight uses (System.dll, mscorlib.dll etc.) are not the same as the basic .NET assemblies although many of the functions exist in both. You could say that the Silverlight assemblies are a slim-down version of the full .NET assemblies, but are almost identical in the functions both expose.
So, basically, if we could modify our public assembly to reference the Silverlight version of these assemblies without modifying the code, we could re-use our public assembly in our Silverlight app.
MSIL Assemblies
Basically, when you write you code in any .NET language (C#, VB.NET), the compiler compiles the code to what is known as MSIL or Microsoft Intermediate Language. This code is then assembled into a .NET Assembly that gets loaded and JIT'ed at runtime. Since assembly references are only validated at runtime, we can safely modify the reference of the problematic assemblies to the correct Silverlight assemblies in the IL code, and when the Assembly is loaded through Silverlight, the correct assemblies will already be in memory and the JIT compiler will compile our code against it.
Our Target
So, to keep things simple, what we want to do basically is once the assembly is built, disassemble it back into MSIL, make a few changes in the references (maybe remove some attributes that are not supported by the Silverlight version of the references), and re-assemble the code back into a new assembly that Silverlight can use.
Note: the new assembly we will create can only be used from a Silverlight project, but all the Type signatures will be identical to our original assembly, and so we will be able to share the WCF contracts between the two.
Setting up the Application
The code included is a simple Console application written in C#. It is accompanied by an XML file containing all the settings it needs to run.
Basically, the application needs to know the following information:
- The location of the MSIL Assembler and Disassembler (ilasm.exe and ildasm.exe).
- A list of assemblies that alter between their Silverlight implementation and their .NET counterparts.
- A list of any non-supported attributes located in the original .NET assemblies and that do not exist in the Silverlight ones that must be removed from the IL code.
The XML file looks something like this:
="1.0" ="utf-8"
<SLAsm.Settings xmlns="urn:Silverlight-Assmblies/SLAsmSettings.xsd"
ILAssembler="C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\ilasm.exe"
ILDisassembler="C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin\ildasm.exe">
<ExternAssembly Name="System" Version="2.0.5.0"
PublicKeyToken="7C EC 85 D7 BE A7 79 8E" />
<ExternAssembly Name="mscorlib" Version="2.0.5.0"
PublicKeyToken="7C EC 85 D7 BE A7 79 8E" />
<ExternAssembly Name="System.Core" Version="2.0.5.0"
PublicKeyToken="7C EC 85 D7 BE A7 79 8E" />
<ExternAssembly Name="System.Net" Version="2.0.5.0"
PublicKeyToken="7C EC 85 D7 BE A7 79 8E" />
<ExternAssembly Name="System.Runtime.Serialization"
Version="2.0.5.0" PublicKeyToken="7C EC 85 D7 BE A7 79 8E" />
<ExternAssembly Name="System.Windows"
Version="2.0.5.0" PublicKeyToken="7C EC 85 D7 BE A7 79 8E" />
<ExternAssembly Name="System.Json"
Version="2.0.5.0" PublicKeyToken="31 BF 38 56 AD 36 4E 35" />
<ExternAssembly Name="System.ServiceModel"
Version="2.0.5.0" PublicKeyToken="31 BF 38 56 AD 36 4E 35" >
<UnsupportedAttribute>
System.ServiceModel.FaultContractAttribute
</UnsupportedAttribute>
<UnsupportedAttribute>
System.ServiceModel.DeliveryRequirementsAttribute
</UnsupportedAttribute>
<UnsupportedAttribute>
System.ServiceModel.CallbackBehaviorAttribute
</UnsupportedAttribute>
<UnsupportedAttribute>
System.ServiceModel.MessageHeaderAttribute
</UnsupportedAttribute>
<UnsupportedAttribute>
System.ServiceModel.MessageHeaderArrayAttribute
</UnsupportedAttribute>
<UnsupportedAttribute>
System.ServiceModel.MessagePropertyAttribute
</UnsupportedAttribute>
<UnsupportedAttribute>
System.ServiceModel.OperationBehaviorAttribute
</UnsupportedAttribute>
<UnsupportedAttribute>
System.ServiceModel.ServiceBehaviorAttribute
</UnsupportedAttribute>
<UnsupportedAttribute>
System.ServiceModel.XmlSerializerFormatAttribute
</UnsupportedAttribute>
<UnsupportedAttribute>
System.ServiceModel.PeerHopCountAttribute
</UnsupportedAttribute>
<UnsupportedAttribute>
System.ServiceModel.TransactionFlowAttribute
</UnsupportedAttribute>
<UnsupportedAttribute>
System.ServiceModel.Activation.AspNetCompatibilityRequirementsAttribute
</UnsupportedAttribute>
</ExternAssembly>
</SLAsm.Settings>
Remember to set the correct paths to the ILAsm.exe and ILdasm.exe files
I have pre-populated the file with all the Silverlight assembly references and added a list of unsupported attributes to the System.ServiceModel assembly.
Note: this is not a complete list of unsuported attributes, rather the ones I have run into myself. Feel free to add any attributes you find that are not working with Silverlight. (You know when your Silverlight app throws a TypeLoadException when it attempts to load your assembly.)
Using the Code
Now that you have set up the XML file, you will probably want to use the code. The application is a simple console app that takes the following arguments:
<AssemblyPath.dll> [/Key=<StrongNameKeyPath.snk>] [/Output=<TargetPath.dll>]
where AssemblyPath.dll is the path to your public .NET assembly. The optional /Output switch specifies where you want to store your new Silverlight assembly. (If you leave this blank, the output file will be AssemblyPath.SL.dll.)
And finally, since we messed all the original IL code, if the original assembly was signed with a strong name key, the newly created assembly will not be properly signed, so you can include the path to the original .snk file you used to sign your assembly, and the app will put it all back together
Setting up as a Post-Build Event
The best way to make sure your public assembly gets converted into a Silverlight compatible one and stays updated whenever you modify it is to add a Post-Build command to your project. To do this, right click on your project and click on the 'Project Properties' menu item.
Navigate to the 'Build Events' tab:

Now, click on the 'Edit Post-build' command, and a dialog opens:

Enter the path to our converter application followed by the "$(TargetPath)" macro to specify the built assembly as the file that will be converted. Add any extra arguments (like the /Output= and /Key=) you need and click on 'OK'.
In the 'Build Events' tab, make sure the option for 'Run the post-build event:' is set to 'On successful build'. Save the project. From here on, whenever your project builds successfully, Visual-Studio will run our app and create a Silverlight compatible assembly of the project.
Note: if the creation of the compatible assembly fails, the entire project will be marked as 'Build Failed', and you will see the error message returned by ilasm.exe in your output window.
Conclusion
I hope this is useful to anyone out there that may have hit the same issue, and if it did help, be sure to drop me a line...
History
- 2009 01 22 - Updated source to load ilasm.exe from the .NET installation folder, also included ildasm.exe in the solution for those of you who don't have the .NET SDK installed.
- 2009 03 03 - Updated the Remove unsupported attributes feature to support methods with more than one attribute (as pointed out by Boris Modylevsky)
| You must Sign In to use this message board. |
|
|
 |
|
 |
When it tries to reassemble the dll it throws an exception:
CouponJoe.Services.il(1303) : error : syntax error at token 'System.Core' in: IL_0046: ldtoken int32 [System.Core]System.Linq.Enumerable::Count<class CouponJoe.Services.Models.CouponUser>(class [mscorlib]System.Collections.Generic .IEnumerable`1<!!0>,
***** FAILURE *****
The line that throws the exception:
IL_0046: ldtoken int32 [System.Core]System.Linq.Enumerable::Count<class CouponJoe.Services.Models.CouponUser>(class [mscorlib]System.Collections.Generic.IEnumerable`1<!!0>, class [System.Core]System.Func`2<!!0,bool>
Justin Toth http://tothsolutions.com
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
 |
I was actually using the incorrect ildasm executable, I was using 2.0's, which doesn't recognize System.Core. Anyhow, I ended up ditching this approach and going with RIA, as even if you do this, you still can't reference your linq to sql entities within your Silverlight app.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
 |
Hello, I changed .xml and everything correctly, I am getting below error cud U plz help ?
C:\XYZ\bin\Debug\Microsoft.GPD.FFJ.dll Disassembling 'C:\XYZ\bin\Debug\Microsoft.GPD.FFJ.dll' Fixing Assembly references... Fixing Assembly reference for 'System' Fixing Assembly reference for 'mscorlib' Removing Strong name Key... Re-Assembling File... Microsoft.GPD.FFJ.il(82) : error : syntax error at token '*' in: *.i..
***** FAILURE ***** ILAsm Faild!
---------------------------------------- My XML file content:
<?xml version="1.0" encoding="utf-8" ?> <SLAsm.Settings xmlns="urn:Silverlight-Assmblies/SLAsmSettings.xsd" ILAssembler="C:\Windows\Microsoft.NET\Framework\v2.0.50727\ilasm.exe"> ILDisassembler="C:\SLAsm\SLAsm\Disassembler\ildasm.exe"/> <ExternAssembly Name="System" Version="2.0.5.0" PublicKeyToken="7C EC 85 D7 BE A7 79 8E" /> <ExternAssembly Name="mscorlib" Version="2.0.5.0" PublicKeyToken="7C EC 85 D7 BE A7 79 8E" /> <ExternAssembly Name="System.Core" Version="2.0.5.0" PublicKeyToken="7C EC 85 D7 BE A7 79 8E" /> <ExternAssembly Name="System.Net" Version="2.0.5.0" PublicKeyToken="7C EC 85 D7 BE A7 79 8E" /> <ExternAssembly Name="System.Runtime.Serialization" Version="2.0.5.0" PublicKeyToken="7C EC 85 D7 BE A7 79 8E" /> <ExternAssembly Name="System.Windows" Version="2.0.5.0" PublicKeyToken="7C EC 85 D7 BE A7 79 8E" /> <ExternAssembly Name="System.Json" Version="2.0.5.0" PublicKeyToken="31 BF 38 56 AD 36 4E 35" /> <ExternAssembly Name="System.ServiceModel" Version="2.0.5.0" PublicKeyToken="31 BF 38 56 AD 36 4E 35" > <UnsupportedAttribute>System.ServiceModel.FaultContractAttribute</UnsupportedAttribute> <UnsupportedAttribute>System.ServiceModel.DeliveryRequirementsAttribute</UnsupportedAttribute> <UnsupportedAttribute>System.ServiceModel.CallbackBehaviorAttribute</UnsupportedAttribute> <UnsupportedAttribute>System.ServiceModel.MessageHeaderAttribute</UnsupportedAttribute> <UnsupportedAttribute>System.ServiceModel.MessageHeaderArrayAttribute</UnsupportedAttribute> <UnsupportedAttribute>System.ServiceModel.MessagePropertyAttribute</UnsupportedAttribute> <UnsupportedAttribute>System.ServiceModel.OperationBehaviorAttribute</UnsupportedAttribute> <UnsupportedAttribute>System.ServiceModel.ServiceBehaviorAttribute</UnsupportedAttribute> <UnsupportedAttribute>System.ServiceModel.XmlSerializerFormatAttribute</UnsupportedAttribute> <UnsupportedAttribute>System.ServiceModel.PeerHopCountAttribute</UnsupportedAttribute> <UnsupportedAttribute>System.ServiceModel.TransactionFlowAttribute</UnsupportedAttribute> <UnsupportedAttribute>System.ServiceModel.Activation.AspNetCompatibilityRequirementsAttribute</UnsupportedAttribute> </ExternAssembly> </SLAsm.Settings>
Best Regards, Supriya Tonape
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
I'm not sure if your question was ever answered, however I ran into the same problem. I stepped through the code and I think if you edit the code that looked like this:
if (!string.IsNullOrEmpty(KeyFile)) sParams += string.Format(" /key=\"{0}\"", args[0]);
and replace it with:
if (!string.IsNullOrEmpty(KeyFile)) sParams += string.Format(" /key=\"{0}\"", KeyFile);
you might be OK. There's an assumption about the order or args that could be screwing you up.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
hi suriel, Thanks for sharing your really wonderful Article. Can i use the same application to convert my MFc Dlls?? What changes i will have to do?
Regards Samir Satardekar
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
I want to add following references to my SilverLight application project(Silverlight 2.0) Can you help me in converting these .Net Assemblies into Silverlight assemblies.Also,state the attributes of these assemblies which are not supported by SilverLight verrsion.
1) Microsoft.Practices.EnterpriseLibrary.Common (version 4.1.0.0) 2) Microsoft.Practices.EnterpriseLibrary.Logging (version 4.1.0.0) 3) Microsoft.Practices.EnterpriseLibrary.ExceptionHandling (version 4.1.0.0)
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
First of all, thanks for your cool articles! 
This might be a dumb question, but would it be possible to achieve the same result (a single assembly codebase that serves both Silverlight and non-Silverlight clients) by having 2 distinct projects (one a Silverlight class lib, the other a non-SL class lib) and having the Silverlight project simply contain links to the single set of source files in the non-SL project?
/ravi
|
| Sign In·View Thread·PermaLink | 1.00/5 |
|
|
|
 |
|
 |
That is definatly an approach taken by others, however it does have its flaws: first off by building it in a seperate project the type signatures will differ (public key token etc...)
second you would have no way of extracting problematic attributes from your code (you could opt to add a compiler symbol and use #if but thats just messy)
thirdly (and I think i'm pointing out the obviouse) you would have to maintain two identical project structures (e.g every addition of a new file would have to be done in both) which seems to me as a hastle
and lastly it don't help you if you don't have the source code 
the solution presented here is just a "quick and dirty" one, note that the tool can be used standalone and not as a post build task
To Err is human, to Arr is Pirate!
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Thank you for this article. It really helps to reuse code for both server and client side, especially contract interfaces and classes that define data contract.
There is only one slight problem: when there is more than one Unsupported Attribute on a method - all its attributes are removed. The problem is within RemoveAttributes method, or even more precisely, in its regular expression. The regular expression matches ALL the attributes of a method, and this match is replaced by a comment.
Thanks again for the article!
|
| Sign In·View Thread·PermaLink | 2.00/5 |
|
|
|
 |
|
 |
Thanks for pointing this out... I have sent in an updated version of the source files so they should be updated soon.
To Err is human, to Arr is Pirate!
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Thanks for the quick reply and fix. It seems, that they did not update the source with your fix.
Could you please send them to my email?
borismod gmail com
Thanks a lot, Boris
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
The sources are updated and I've just tested the recent version. The issue, I pointed out earlier, is resolved indeed. Accept my appreciation for the quick fix.
Unfortunately, my colleague Tomer and me encountered two more issues with the attributes removal:
1. When the following attribute is specified on interface contract, SessionMode remains in the Silverlight version of the DLL, but it does not exist in System.ServiceModel.dll of Silverlight, just in .NET 3.5. [ServiceContract(Namespace = "urn:MyFavoriteNamespace",SessionMode=SessionMode.Allowed)]
2. We specify the following attributes a method within a contract [OperationContract] [WebGet(ResponseFormat = WebMessageFormat.Json)] WebGet attribute belongs to System.SystemModel.Web.dll, which does not exist in Silverlight. Currently there is no way in SLasm.exe to specify UnsupportedAttribute of an assembly, that is not an external assembly.
Thanks in advance!
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
As to the first issue, if I understand correctly the issue is that the attribute has an overload that does not exist in the SL version... I'm not sure of how to tackle this issue at the moment but give me a bit of time and I'll se what i can do...
As to the second issue, If I understand your issue i belive you could use a simple workaround: Add the System.SystemModel.Web.dll to the list of ExternAssembly and just give it the same version and publickkeytoken as the original (so in fact the replace will not do anything) and then add the list of unsupported attributes to it...
To Err is human, to Arr is Pirate!
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Your understanding is correct and your suggestion for the first issue resolved it. I added the following to configuration file and the attribute was removed by SLasm.exe:
System.ServiceModel.Web.WebGetAttribute
However, when opening the resulting Silverlight DLL in Reflector displays that there is a reference to a .NET 3.5 dll, which is strange, but works fine.
Take your time to resolve the second one!
Best regards, Boris Modylevsky
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
your converter is not allowing to convert the assemvlies of version 3.1.0.0. i am tryin to convert Microsoft.Practices.EnterpriseLibrary.Validation.dll for silverlight but it is givin an error as shown below
F:\SMS demo\parth\SLAsm\SLAsm\bin\Debug>SLAsm.exe "F:\DOTNET_APP_Framework\Source\bin\Debug\Microsoft.Practices.Enterprise Library.Common.dll" Disassembling 'F:\DOTNET_APP_Framework\Source\bin\Debug\Microsoft.Practices.EnterpriseLibrary.Common.dll' Fixing Assembly references... Fixing Assembly reference for 'System' Fixing Assembly reference for 'mscorlib' Removing Strong name Key... Re-Assembling File... Microsoft.Practices.EnterpriseLibrary.Common.il(241) : error : syntax error at t oken '.2' in: .2.......!..... ***** FAILURE ***** ILAsm Faild!
can u pls help it out.. or is ther any alternative for silverlight..
Regards, Parth.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
The tool is not meant for converting full enterprise libraries however if you mail me the assembly that is failing I will look into it...
To Err is human, to Arr is Pirate!
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
This has saved me no end of time converting a fairly simple puzzle engine for use in a silverlight application. Well done.
NB: There is a really minor problem when you execute the application and don't specify a path to the target assembly (i.e. if the assembly to convert is copied to the same folder as the console EXE) as it throws an exception when trying to create a directory to nowhere..
--- Regards Steve
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Instead of checking each attribute against a manually-maintained list of unsupported attributes, why not instead simply look at each attribute that references System.dll, mscorlib.dll, etc., and check to see whether that attribute exists in the Silverlight runtime dll.
Perhaps the same could be done for method calls and BCL classes. Check whether Silverlight supports each .NET method and class used by an assembly and emit an error if not.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Have you thought about (do you know of) a "Silverlight Cop" utility that will highlight those features in an assembly that are not compatible with Silverlight?
|
| Sign In·View Thread·PermaLink | 4.60/5 |
|
|
|
 |
|
 |
Hi,
Nice to hear this.
I have 2 question
1. If you could tell me, is "Silverlight Cop" freeware or Microsoft Build-in tool. 2. Where can we get this tool.
waiting for your reply ASAP.
Thanks in Advance!!!
-Baskaran.D
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Hi Suriel,
The download link contains some invalid spaces: http://www.codeproject.com/KB/silverlight/%22SLAssemblies/SLAsm.zip%22
It should be: http://www.codeproject.com/KB/silverlight/SLAssemblies/SLAsm.zip
Cheers, Jani
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|