[IronPython] Monkey-patching CLR types

Dino Viehland dinov at microsoft.com
Tue Feb 16 04:18:01 CET 2010


If you strongly type handler to a delegate type IronPython should
convert the function to the delegate type on the call.  I had meant to
write "EventHandler<HtmlEventArgs>" in my original sample code but somehow
I ended up using the Python syntax EventHandler[HtmlEventArgs] :)

Yeah, the comment's write, I'm wrong http://msdn.microsoft.com/en-us/library/2sk3x8a7(VS.71).aspx
lists op_AdditionAssignment but not InPlaceAdd.


> -----Original Message-----
> From: users-bounces at lists.ironpython.com [mailto:users-
> bounces at lists.ironpython.com] On Behalf Of Jimmy Schementi
> Sent: Monday, February 15, 2010 7:08 PM
> To: Discussion of IronPython
> Subject: Re: [IronPython] Monkey-patching CLR types
> 
> Thanks Dino!
> 
> I've got something to at least compile, but I'm getting the error
> "ArgumentTypeException: unsupported operand type(s) for +=:
> 'PythonBrowserEvent' and 'function'". OK, makes sense, it's not finding
> InPlaceAdd(Python.Runtime.Method), right? Since I can't link against
> IronPython, what type should I use instead of Python.Runtime.Method?
> System.Dynamic.IDynamicMetaObjectProvider, as that's the only DLR
> interface that Method implements? If so, then I'm not sure how to
> convert it to an Action<object, HtmlEventArgs>.
> 
> Also, should I be using "op_AdditionAssignment" instead of InPlaceAdd?
> The usage in ReflectedEvent.cs
> (http://ironpython.codeplex.com/sourcecontrol/changeset/view/63991?proj
> ectName=IronPython#384571) seems to say that.
> 
> If it helps, here's what I have so far:
> 
>     public static class HtmlElementExtension {
>         [SpecialName]
>         public static object GetBoundMember(HtmlElement element, string
> name) {
>             object propertyValue = element.GetProperty(name);
>             // No way to tell if a property actually exists, so best we
> can do
>             // do is check if it's null ...
>             if (propertyValue == null) {
>                 return new PythonBrowserEvent(element, name);
>             }
>             return propertyValue;
>         }
>     }
> 
>     public class PythonBrowserEvent {
>         private readonly HtmlElement _element;
>         private readonly string _event;
> 
>         internal PythonBrowserEvent(HtmlElement element, string
> eventStr) {
>             _element = element;
>             _event = eventStr;
>         }
> 
>         [SpecialName]
>         public object InPlaceAdd(object handler) {
>             _element.AttachEvent(_event,
>                 new EventHandler<HtmlEventArgs>((Action<object,
> HtmlEventArgs>)handler));
>             return null;
>         }
>     }
> 
> > -----Original Message-----
> > From: users-bounces at lists.ironpython.com [mailto:users-
> > bounces at lists.ironpython.com] On Behalf Of Dino Viehland
> > Sent: Sunday, February 14, 2010 4:58 PM
> > To: Discussion of IronPython
> > Subject: Re: [IronPython] Monkey-patching CLR types
> >
> > You can define an extension property that gets/sets a value which
> supports in
> > place addition / subtraction.  Something like this:
> >
> >     [assembly: ExtensionType(typeof(HtmlElement),
> > typeof(HtmlElementExtension))]
> >     public static class HtmlElementExtension {
> >         [SpecialName, PropertyMethod]
> >         public static MyEvent Getonclick(HtmlElement element) {
> >              return new MyEvent(element);
> >         }
> >         [SpecialName, PropertyMethod]
> >         public static void Setonclick(HtmlElement element, object
> value) {
> > 		// You could return a value from InPlaceAdd and validate it
> > here
> > 		// to report an error on a direct assignment - this is what
> > 		// ReflectedEvent does in IronPython.
> >         }
> >     }
> >
> >     public class MyEvent {
> >          private readonly HtmlElement _element;
> > 	   public MyEvent(HtmlElement element) {
> >               _element = element;
> >          }
> > 	   [SpecialName]
> >          public object InPlaceAdd(EventHandler[HtmlEventArgs]
> handler) {
> >               _element.AttachEvent("onclick", handler);
> > 		  return null;
> >          }
> > 	   // also needs InPlaceSubtract
> >     }
> >
> > -----Original Message-----
> > From: users-bounces at lists.ironpython.com [mailto:users-
> > bounces at lists.ironpython.com] On Behalf Of Jimmy Schementi
> > Sent: Sunday, February 14, 2010 2:06 PM
> > To: Discussion of IronPython
> > Subject: [IronPython] Monkey-patching CLR types
> >
> > (Yes, I'm asking a question this time =P)
> >
> > I want to know my options for adding functionality to an existing CLR
> type.
> > Specifically I want to make hooking DOM events cleaner: in
> Silverlight today
> > you cannot hook DOM events with the standard += syntax that
> IronPython uses
> > for CLR events:
> >
> >     object.onclick += foo
> >
> > Instead you must do this:
> >
> >     object.AttachEvent("onclick", EventHandler[HtmlEventArgs](foo))
> >
> > In IronRuby I fixed that by just monkey-patching
> > System.Windows.Browser.HtmlObject, but in IronPython I cannot monkey-
> patch
> > built-in types. However, I do something similar with accessing DOM
> properties
> > (instead of element.GetProperty("innerHTML") it's just
> element.innerHTML)
> > with DLR's ExtensionType, which is the same way IronPython exposes
> special
> > methods on CLR types as well:
> >
> >     [assembly: ExtensionType(typeof(HtmlElement),
> > typeof(HtmlElementExtension))]
> >     public static class HtmlElementExtension {
> >         [SpecialName]
> >         public static object GetBoundMember(HtmlElement element,
> string name)
> > {
> >             return element.GetProperty(name);
> >         }
> >     }
> >
> > But after looking through Python's Binder and the DLR's ActionBinder
> for how
> > they use ExtensionTypes, I couldn't get a definitive answer on how to
> capture
> > an method call plus an operator. Any ideas?
> >
> > ~Jimmy
> >
> > _______________________________________________
> > Users mailing list
> > Users at lists.ironpython.com
> > http://lists.ironpython.com/listinfo.cgi/users-ironpython.com
> > _______________________________________________
> > Users mailing list
> > Users at lists.ironpython.com
> > http://lists.ironpython.com/listinfo.cgi/users-ironpython.com
> 
> _______________________________________________
> Users mailing list
> Users at lists.ironpython.com
> http://lists.ironpython.com/listinfo.cgi/users-ironpython.com




More information about the Ironpython-users mailing list