Welcome to MSDN Blogs Sign in | Join | Help

Consuming Extension Methods in IronPython

[Update on 2008-01-06]

I’ve modified the post to reflect the information Dino provided. It turns out the SpecialName attribute is not required on extension methods but only when you are defining normal extension methods only when defining new operators.

 

One of my projects implemented in C# makes frequent use of extension methods. Recently I started using IronPython to script that project and what I learned is that consuming those extension methods in C# is straightforward but with IronPython some extra work is involved.

Because it isn’t entirely obvious what one needs to do to make this work, I’ll use  this post to elaborate what I learned.

The diagram below summarizes it …

image

THE GOOD NEWS

  • It’s possible
  • You do NOT have to alter class A (“the extendee”)

THE BAD NEWS

  • manual and repetitive work is involved

STEP-BY-STEP INSTRUCTIONS TO MODIFY THE EXTENDING CLASS

1 - Add a reference to Microsoft.Scripting.Dll

In the Visual Studio project file for B, Add a reference to the Microsoft.Scripting.Dll file (this is found in the IronPython 2.0 install folder)

2 – Add an attribute that identifies that B extends A

image

Add this at the top of B’s source file, just after the using statements.

 

A REAL BEFORE vs. AFTER COMPARISON

In this example

  • we will add a Foo() method to a class we defined as well as to the string class (a.k.a System.String)
  • Both Foo() methods just return a string called Bar
  • The Dll that contains the extensionmethods is called “DemoIronPythonExtensionMethods.dll”
  • The role of B will be played by DemoExtensionClass
  • The role of A will be played by two classes – System.String and ClassToBeExtended

SOURCE CODE BEFORE

SOURCE CODE AFTER

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DemoIronPythonExtensionMethods
{
    public class ClassToBeExtended
    {
    }

    public static class DemoExtensionClass
    {
        public static string Foo(this string s)
        {
            return "Bar";
        }

        public static string Foo(this ClassToBeExtended c)
        {
            return "Bar";
        }
    }

}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

[assembly: Microsoft.Scripting.Runtime.ExtensionType(
    typeof(DemoIronPythonExtensionMethods.ClassToBeExtended),
    typeof(DemoIronPythonExtensionMethods.DemoExtensionClass)
    )]

[assembly: Microsoft.Scripting.Runtime.ExtensionType(
    typeof(string),
    typeof(DemoIronPythonExtensionMethods.DemoExtensionClass)
    )]
 

namespace DemoIronPythonExtensionMethods
{
    public class ClassToBeExtended
    {
    }

    public static class DemoExtensionClass
    { 
        public static string Foo(this string s)
        {
            return "Bar";
        }

        public static string Foo(this ClassToBeExtended c)
        {
            return "Bar";
        }
    }

}

   

WHAT HAPPENS IN IRONPYTHON 2 BEFORE

WHAT HAPPENS IN IRONPYTHON 2 AFTER

>>> import clr
>>> import System
>>> clr.AddReference("DemoIronPythonExtensionMethods.dll")
>>> import DemoIronPythonExtensionMethods
>>> c1 = DemoIronPythonExtensionMethods.ClassToBeExtended()
>>> c1.Foo()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'ClassToBeExtended' object has no attribute 'Foo'

>>> s1= "HELLO WORLD"
>>> s1.Foo()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'str' object has no attribute 'Foo'

>>> import clr
>>> import System
>>> clr.AddReference("DemoIronPythonExtensionMethods.dll")
>>> import DemoIronPythonExtensionMethods
>>> c1 = DemoIronPythonExtensionMethods.ClassToBeExtended()
>>> c1.Foo()
'Bar'
>>> s1= "HELLO WORLD"
>>> s1.Foo()
'Bar'

PARTING THOUGHTS

  • I it is a bit of a chore to annotating once per extending class.
  • I hope this becomes easier in future IronPython releases
  • I wonder if one could use an Aspect-Oriented Programming Tool like PostSharp to automate the task.
Published Friday, November 14, 2008 6:56 PM by saveenr

Attachment(s): Consuming-Extension-Methods-in-IronPython-2-(2008-11-17).vsd

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

# Consuming Extension Methods in IronPython | Tmao Coders

Friday, November 14, 2008 10:02 PM by Consuming Extension Methods in IronPython | Tmao Coders

# re: Consuming Extension Methods in IronPython

IIRC, there a reasonably isolated bit of code that governs member resolution.  I tried hacking it into IP1.x some time ago, but didn't follow up on it.

Might be entertaining to look into.

Friday, November 14, 2008 10:09 PM by kfarmer

# re: Consuming Extension Methods in IronPython

You shouldn't need the SpecialName attribute to make this work - we use this elsewhere (e.g. StringOps) and don't need to use SpecialName.  SpecialName should only be used when you're defining new operator methods.

Tuesday, January 06, 2009 10:33 PM by Dino Viehland

# re: Consuming Extension Methods in IronPython

Dino - thanks for the information. I have updated the post to reflect that SpecialName is not needed for these extension methods.

Wednesday, January 07, 2009 2:59 AM by saveenr

# IronPython: Consuming Extension Methods in IronPython Part II

Friday, February 06, 2009 12:38 AM by Saveen Reddy's blog

Leave a Comment

(required) 
required 
(required) 
 
Page view tracker