In the previous post I showed how to consume extension methods without modifying either the assembly containing the extension methods or the assembly being extended. The price for this was having to create a third assembly. In this post, I will bring the scenario much close to the desired state.

Before I do that, I will illustrate how I would like IronPython to behave.

First, again we have two assemblies …

image

image

WE WANT THIS

And what we would like to do is simply consume the extension methods  - something like this

image

As I demonstrated in my last post, it’s not that simple.

Until now.

WE CAN GET VERY CLOSE TO THE DESIRED BEHAVIOR

A little bit of C# and some CodeDOM magic and we can do this…

image

A CLOSER LOOK AT import_extension_methods()

image

TECHNICAL DETAILS

  • The source is attached
  • The Isotope.IronPythonUtil is an assembly that contains a method CreateIronPythonExtensionMethodAssembly()
  • CreateIronPythonExtensionMethodAssembly()
    • loads an assembly from a DLL
    • loads all the assemblies to which that first assembly refers
    • finds all the extension methods in the first assembly
    • builds a CodeDOM of all the ExtensionType attributes
    • builds a placeholder class (see previous post about the need for this)
    • and generates a DLL
  • The original code generated a “C#” file and used CodeDOM to compile it to an DLL. This one generates a CodeDOM manually so it is faster to create the Dll.
  • The source code is included as an attachment

PARTING THOUGHTS

  • The situation is much improved now
  • There’s a little bit of delay in generating and loading this third assembly, but it’s nothing unreasonable relative to the general speed of IronPython import speed
  • we should just be able to keep that 3rd dynamically created assembly in memory and not persist it to disk – QED
  • Ultimately I hope this support arrives “out-of-the-box” with IronPython. It’s just part of supporting the “batteries included” principle.