Skip to content

Instantly share code, notes, and snippets.

@delicb
Created July 25, 2014 13:43
Show Gist options
  • Save delicb/bb367688f62a412b39f9 to your computer and use it in GitHub Desktop.
Save delicb/bb367688f62a412b39f9 to your computer and use it in GitHub Desktop.
IronPython CLR __clrtype__ manipultaion example
# from http://devhawk.net/2009/04/21/__clrtype__-metaclasses-ironpython-classes-under-the-hood/
import clr
clr.AddReference('Microsoft.Scripting.dll')
clr.AddReference('Microsoft.Dynamic.dll')
clr.AddReference('IronPython.dll')
from Microsoft.Scripting.Generation import Snippets
from System.Reflection.Emit import OpCodes
from System.Reflection import FieldAttributes
from IronPython.Runtime.Types import ReflectedField
class ClrTypeMetaclass(type):
def __clrtype__(cls):
baseType = super(ClrTypeMetaclass, cls).__clrtype__()
typename = cls._clrnamespace + "." + cls.__name__ if hasattr(cls, '_clrnamespace') else cls.__name__
typegen = Snippets.Shared.DefineType(typename, baseType, True, False)
typebld = typegen.TypeBuilder
for ctor in baseType.GetConstructors():
ctorparams = ctor.GetParameters()
ctorbld = typebld.DefineConstructor(ctor.Attributes, ctor.CallingConvention, tuple([p.ParameterType for p in ctorparams]))
ilgen = ctorbld.GetILGenerator()
ilgen.Emit(OpCodes.Ldarg, 0)
for index in range(len(ctorparams)):
ilgen.Emit(OpCodes.Ldarg, index + 1)
ilgen.Emit(OpCodes.Call, ctor)
ilgen.Emit(OpCodes.Ret)
if hasattr(cls, "_clrfields"):
for fldname in cls._clrfields:
typebld.DefineField(fldname, clr.GetClrType(cls._clrfields[fldname]), FieldAttributes.Public)
new_type = typebld.CreateType()
if hasattr(cls, "_clrfields"):
for fldname in cls._clrfields:
fldinfo = new_type.GetField(fldname)
setattr(cls, fldname, ReflectedField(fldinfo))
return new_type
class Product(object):
__metaclass__ = ClrTypeMetaclass
_clrnamespace = "DevHawk.IronPython.ClrTypeSeries"
_clrfields = {
'name': str,
'cost': float,
'quantity': int,
}
def __init__(self, name, cost, quantity):
self.name = name
self.cost = cost
self.quantity = quantity
def calc_total(self):
return self.cost * self.quantity
p = Product('Crunchy Frog', 5.99, 10)
t = p.GetType()
print(p.name)
namefi = t.GetField('name')
print(namefi.GetValue(p))
namefi.SetValue(p, 'Spring Supprise')
print(p.name)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment