Updated findings:
According to the IronPython docs, “Extension methods are currently not natively supported by IronPython. Hence, they cannot be invoked like instance methods. Instead, they have to be invoked like static methods.”
I’m not 100% sure what that means, but I assume there is no direct and easy way to use extension methods, even though IronPython is written in C#, which has them.
My next thought was to code all the extension methods in C#, then import them into IronPython. I found examples that do exactly that, and so I attempted it. It worked! Create a C# static class like this, following the standard practice for extension methods in C#:
using Autodesk.Revit.DB;
namespace ExtensionMethods
{
public static class Element_Ext
{
public static string ExtensionTest(this Element elem)
{
return elem.Name + " Extension Method Test";
}
}
}
Then import that into IronPython by first importing it from the namespace, then using clr.ImportExtensions on the extension method itself:
import clr
clr.AddReferenceToFileAndPath(r"...ExtensionMethodsProject\bin\Debug\net8.0\ExtensionMethodsProject.dll")
from ExtensionMethods import Element_Ext
clr.ImportExtensions(Element_Ext)
# Now you can call the extension method on any instance of the extended class
print a_revit_API_Element.ExtensionTest() # prints "{Element.Name} Extension Method Test"
This is very cool, but unfortunately, there are problems. I created the C# project using .NET 8, so it does not work in older versions of Revit. I would have to build different versions of the dll for the different versions of Revit. Also, there is probably a better way to add the dll reference within IronPython so that it doesn’t rely on an absolute path to the dll, but I don’t know how to do this. Referencing an absolute path obviously won’t work when deploying my pyRevit extension to multiple users.
So, unfortunately, I don’t think I will be using these extension methods because it ended up being more complex than the python wrapper class I was originally using for this functionality. The whole point was to simplify my development cycle, but now that I am working with multiple languages, targeting multiple .NET versions and multiple Revit versions, re-compiling, and re-deploying with every change, the advantage is no longer there. Shame!
(If I could find a way to use extension methods directly in IronPython, then I totally would!)