views:

141

answers:

2

is it possible to do this in IronPython and if it is, how?

+2  A: 

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.

jcao219
I need to use .NET's Binary Serialization.
Pablo
thanks for the reply, take a look at my second post if this interests you :)
Pablo
A: 

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

Pablo