[Python.NET] Subclassing CLR types
Michael Amrhein
Michael.Amrhein at t-online.de
Thu Oct 30 17:48:39 EST 2003
Hi,
subclassing CLR types does work as long as you hold a reference to the
instance of the subclass in Python. But when you pass a subclassed
object to a CLR object and retrieve this object later through a method
of the CLR object you don't get an instance of the subclass but an
instance of the CLR base class the subclass was derived from:
Python 2.3.2 (#49, Oct 2 2003, 20:02:00) [MSC v.1200 32 bit (Intel)] on
win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import CLR
>>> from CLR.System.Windows.Forms import Control
>>> c=Control("This is a Control.")
>>> class myControl(Control):
... def dummy(self):
... return self.Text
...
>>> m=myControl(c, "This is a myControl.")
>>> m.Parent
<CLR.System.Windows.Forms.Control object at 0x008F6F70>
>>> m.Parent.Text
u'This is a Control.'
>>> c.Contains(m)
True
>>> m.dummy()
u'This is a myControl.'
>>> c.Controls[0] == m
True
[Every thing ok, so far, but ...]
>>> c.Controls[0].dummy()
Traceback (most recent call last):
File "<stdin>", line 1, in ?
AttributeError: 'Control' object has no attribute 'dummy'
[Because ...]
>>> type(c.Controls[0])
<class 'CLR.System.Windows.Forms.Control'>
This is weird because it means that when I get back an instance of a
subclass from some CLR method I don't know the correct type and can not
act on it properly.
I don't know if there's an easy way to come around this problem but to
me subclassing of CLR types seemes pretty useless without a solution for it.
If there is some kind of unique reference from the Python wrapper
instances to the CLR instances a starting point for a solution may be to
base all wrappers on a base type which keeps a mapping of referenced CLR
instances to wrapper instances.
Something like this (all not tested yet!!!):
class CLRObj(object):
from weakref import WeakValueDictionary
__objMap = WeakValueDictionary()
def __new__(cls, ref):
try:
obj = clrObj.__objMap[ref]
except KeyError:
obj = object.__new__(cls)
obj._ref = ref
clrObj.__objMap[ref] = obj
return obj
def __del__(self):
self._ref.Dispose()
class <wrapper>(CLRObj):
def __new__(cls, ...):
ref = <create base CLR type>
return CLRObj.__new__(cls, ref)
... and when receiving a CLR instance turn it into the corresponding
wrapper instance by
obj = CLRObj(clrObj)
This will not work if you receive some kind of CLR object which was
created internally by some CLR method and not through a wrapper. But you
will get all object you created through the wrappers back as instances
of the correct type.
If I'm galloping in the wrong direction please give me a short stop
signal. If not ... lets figure out the probably missing details.
Michael
More information about the PythonDotNet
mailing list