Tuesday, October 28, 2008

IronPython 2 and the Fifth Assembly

IronPython 2 uses Dynamic Language Runtime expression trees, which have been merged with LINQ expression trees. These have extension methods and IronPython itself also uses extension methods. These need the .NET 3.5 compiler, but if you provide an 'ExtensionAttribute' type then the compiled assemblies still work with .NET 2 (extension methods are effectively a compiler trick).

Unfortunately the 'ExtensionAttribute' type supplied with IronPython 2 clashes with the version in .NET 3.5 if your project also references the System.Core assembly.

The latest release candidate of IronPython solves this problem by providing a fifth assembly. Harry Pierson (DevHawk) gives us the details: The important details are:

In IronPython 2.0 Beta 5, there were four DLLs that implement IronPython:
  • IronPython.dll
  • IronPython.Modules.dll
  • Microsoft.Scripting.dll
  • Microsoft.Scripting.Core.dll
In our RC1 release, we’ve added “The Fifth Assembly”: Microsoft.Scripting.ExtensionAttribute.dll. As you might guess from its name, it has only a single public type: ExtensionAttribute. By having ExtensionAttribute in its own dedicated assembly, we can avoid the type collision at compile time by not referencing both System.Core.dll and Microsoft.Scripting.ExtensionAttribute.dll in the same project.

In IronPython, we reference the ExtensionAttribute assembly because we use the C# 3.0 complier but IPy has to be able to run on .NET Framework 2.0 SP1. However, projects that embed IronPython in a .NET 3.5 project (aka C# 3.0 or VB 9.0) will reference System.Core instead. The only reason why you would explicitly use the ExtensionAttribute assembly was that if you, like us, wanted to build your app with .NET 3.5, use extension methods but still be compatible with .NET 2.0 SP1. We’re guessing there aren’t many of our customers doing that, but if you are, explicitly referencing ExtensionAttribute will work just as it does for compiling IronPython itself.

It’s important to remember two things about the Fifth Assembly:
  1. Never reference System.Core and Microsoft.Scripting.ExtensionAttribute in the same project.
  2. Always deploy Microsoft.Scripting.ExtensionAttribute.dll as part of any solution that embeds IronPython (or IronRuby or vanilla DLR for that matter), even if you don’t reference it explicitly within your project.
Unfortunately this still doesn't solve the problem for ASP.NET projects that use .NET 3.5. The valiant IronPython team found another solution, and Curt posted the workaround to the IronPython mailing list:

Here's what we recommend as a workaround.

The CodePlex work item that tracks this request now contains a modified version of Microsoft.Scripting.ExtensionAttribute.dll. For this one particular case, where simultaneous referencing of the original version of our assembly and System.Core.dll causes problems, you can replace the "shipping version" of our DLL with the modified version. This will eliminate the "is ambiguous" error message.

The magic that makes this work is called "type forwarding". The updated DLL simply contains a type forwarder to System.Core for the type System.Runtime.CompilerServices.ExtensionAttribute. As a result, there is no second copy of that class, and the CLR loader redirects all references from the rest of IronPython to System.Core.

This file, though strongly-named and signed, is even more "not supported" than the rest of IronPython :). By this I mean primarily that we haven't run any test passes using the new assembly, and don't plan to. However, as it doesn't actually contain any code, the risks from this modified version should be very small.

We hope to address this problem differently for the next release, but our promise to stay compatible with .NET 2.0 for this release has somewhat constrained the type of solution we are able to offer.

Thanks for your patience!

No comments:

Post a Comment

Note: only a member of this blog may post a comment.