The Fifth Assembly

As I’ve written previously, we’ve had a few challenges recently with name collisions in the DLR. In that post, I described how we had solved – or thought we solved, as it turned out – the problem with ExtensionAttribute name collisions between Microsoft.Scripting.Core.dll and System.dll.

However, as it turns out, having lots of copies of the same type didn’t solve the problem. Since ExtensionAttribute is a known type to the C# 3.0 compiler, it has to choose one of the multiple copies that are in the project. We thought that given a choice, it would favor the System.Core version. However, what folks discovered after we released Beta 5 is that C# 3.0 will choose the first copy of ExtensionAttribute that it finds. So if you have System.Core.dll and IronPython referenced in your project, and you define your own extension methods, the compile fails if the C# 3.0 compiler finds one of the IronPython or DLR private copies of ExtensionAttribute before the public copy in System.Core.

Furthermore, there doesn’t seem to be any way to set the reference order in MSBuild files. I’ve never dug deep into the MSBuild file format, but changing the order of the references in the csproj file didn’t seem to effect the order the references were passed to the C# compiler. I’m guessing we might be able to change this by fiddling with the ResolveAssemblyReference task, but we didn’t want to force low level MSBuild file hacking on our user base.

We looked at a variety of other solutions, including rewriting the IL after compilation to change the namespace of the ExtensionAttribute. However, we had trouble making that solution work and besides, changing the ExtensionAttribute namespace would have broken anyone using the existing DLR or IPy extension methods. So instead, we went with a different solution that we like to refer to as “The Fifth Assembly” around the office.

IPy References

In IronPython 2.0 Beta 5, there were four DLLs that implement IronPython: IronPython.dll, IronPython.Modules.dll, Microsoft.Scripting.dll and 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.

This change is public in the source code as of change set 42076 and will also be in the nearly-ready RC1 release of IronPython 2.0. If you’ve got any questions or <shudder> find any more issues with this solution, please let us know right away.

Comments:

Hi, This is perhaps not the best place to report this, but I couldn't find the associated ticket in the CodePlex issue tracker. I've just updated to RC1. My project is a fairly basic WPF project and references System.Core; it previously got the warning about the duplicate definition. Now when I build I get the following error: Target MarkupCompilePass1: C:WindowsMicrosoft.NETFrameworkv3.5Microsoft.WinFX.targets(294,9): error MC1000: Unknown build error, 'Cannot resolve dependency to assembly 'Microsoft.Scripting.ExtensionAttribute, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' because it has not been preloaded. When using the ReflectionOnly APIs, dependent assemblies must be pre-loaded or loaded on demand through the ReflectionOnlyAssemblyResolve event.' Initially I just used RC1 from the zip file, but I also tried installing from the .msi on the chance the it would install the assemblies into the GAC but it didn't do that. Have I missed something in my project configuration? Thanks, Dave
Harry - Will Microsoft.Scripting.Core and System.Core eventually be merged? I'm hitting some problems using Microsoft.Scripting.Core in a Silverlight 2 project (it wants a System.Core reference too).
@Dave, Did you create a new issue on CodePlex? @Chris, Microsoft.Scripting.Core is essentially the .NET 4.0 version of System.Core. The merge has already been done