Marking an IronPython class as serializable

Can this be done in IronPython, and if so, how?

+3
source share
2 answers

I was given this example by one of IronPython developers to add .NET attributes to python classes such as Serializable.

http://ironpython.codeplex.com/releases/view/36280#DownloadId=116513

+4
source

The Python serialization version is Pickling (I believe). I don't think the class should be labeled serializable.

So you have to do this:

import clr clr.AddReference ("IronPython.Modules")

from IronPython.Modules imports PythonPickle

stored = PythonPickle.dumps( "ASDF" ) recovered = PythonPickle.loads() #recovered - "ASDF"


, ...

, BinaryFormatter , :

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()

, "", , GetObjectData info.AddValue(...)

, , , , IronPython.

+2

Source: https://habr.com/ru/post/1740815/


All Articles