is it possible to do this in IronPython and if it is, how?
Python's version of serialization is Pickling (I believe). I don't think a class has to be marked serializable.
So you have to do this:
import clr clr.AddReference("IronPython.Modules")
from IronPython.Modules import PythonPickle
stored = PythonPickle.dumps("ASDF") recovered = PythonPickle.loads(stored) #recovered is "ASDF"
Well, you can definitely mark one as serializable... I looked into here
and I was able to make it sort-of serializable so that the BinaryFormatter would take it and serialize it, but deserialization is impossible:
from System.IO import File
from System.Runtime.Serialization.Formatters.Binary import BinaryFormatter #whew
from System.Runtime.Serialization import ISerializable, SerializationException
from System import SerializableAttribute, ObsoleteAttribute
from System.Reflection.Emit import OpCodes, CustomAttributeBuilder
from System.Security.Permissions import *
import clr
clr.AddReference("Microsoft.Dynamic")
clr.AddReference("IronPython")
from Microsoft.Scripting.Generation import Snippets
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, '_clrclassattribs'):
for cab in cls._clrclassattribs:
typebld.SetCustomAttribute(cab)
return typebld.CreateType()
def make_cab(attrib_type, *args, **kwds):
clrtype = clr.GetClrType(attrib_type)
argtypes = tuple(map(lambda x:clr.GetClrType(type(x)), args))
ci = clrtype.GetConstructor(argtypes)
props = ([],[])
fields = ([],[])
for kwd in kwds:
pi = clrtype.GetProperty(kwd)
if pi is not None:
props[0].append(pi)
props[1].append(kwds[kwd])
else:
fi = clrtype.GetField(kwd)
if fi is not None:
fields[0].append(fi)
fields[1].append(kwds[kwd])
else:
raise Exception, "No %s Member found on %s" % (kwd, clrtype.Name)
return CustomAttributeBuilder(ci, args,
tuple(props[0]), tuple(props[1]),
tuple(fields[0]), tuple(fields[1]))
def cab_builder(attrib_type):
return lambda *args, **kwds:make_cab(attrib_type, *args, **kwds)
Serializable = cab_builder(SerializableAttribute)
class Applesauce(ISerializable):
__metaclass__ = ClrTypeMetaclass
_clrnamespace = "Yummy.Yum.Food"
_clrclassattribs = [Serializable()]
def __init__(self):
self.sweetness = 10
def GetObjectData(self,info,context):
info.AddValue("sweetness",10)
binformatter = BinaryFormatter()
output = File.Create("applesauce.dat")
binformatter.Serialize(output,Applesauce())
output.Close()
of course, the output file only had the "sweetness" attribute serialized because it was in the GetObjectData method as info.AddValue(...)
So right now, I think it is safe to conclude it is impossible to mark it as serializable in pure IronPython.
I was given this example by one of the IronPython developers, for adding .NET attributes on python classes, such as Serializable.
http://ironpython.codeplex.com/releases/view/36280#DownloadId=116513