2012-12-28 12 views
5

मैं सी # करने के लिए एक जावा खेल को परिवर्तित कर रहा हूँ (पिल्ला खेलों द्वारा टाइटन हमलों) और काफी अब पिछले कार्य जो खेल राज्य की क्रमबद्धता है से अलग किया हूँ फ़ाइलों को बचाने के लिए।नेट क्रमबद्धता - मिश्रण [Serializable] विरासत पेड़ में कस्टम के साथ

ठेठ पदानुक्रम: संसाधन (आधार) -> सुविधा-> स्क्रीन/प्रभाव/Entity-> GameScreen/LaserEffect/हमलावर

जावा कोड का उपयोग करता मानक ObjectOutputStream/ObjectInputStream द्विआधारी क्रमांकन प्रदर्शन करने के लिए, लेकिन annoyingly कुछ readResolve करता है/आधार वर्ग स्तर (संसाधन) पर writeResolve काम क्रमबद्धता प्रक्रिया अनुकूलित करने के लिए (यदि एक संसाधन के नाम पर है यह यह क्रमानुसार नहीं करता है और बस एक ऐसा नाम है जो बाद में प्रयोग किया जाता है एक hashmap से बाहर लाने के लिए संसाधन के साथ एक प्रॉक्सी रिटर्न)।

मेरे अनुभवहीन समाधान आँख बंद करके इस दृष्टिकोण को कॉपी और प्रकार ओवरराइड करने के लिए आधार वर्ग में ISerializable लागू करने के लिए ...

public virtual void GetObjectData(SerializationInfo info, StreamingContext context) { 
    if (name != null) { 
     // Got a name, so send a SerializedResource that just references us 
     info.AddValue("name", this.name); 
     info.SetType(typeof(SerializedResource)); 
     return; 
    } 

    //Serialize just MY fields (defined in Resource) 
    this.SerializeMyFields(info, context, typeof(Resource)); 
} 

क्यू है) तो, मैं बहुत सुनिश्चित करें कि सभी दांव के लिए बनाया गया बंद कर रहे हैं हूँ सीरियलाइजेशन में और मुझे सीरियलाइजेशन कन्स्ट्रक्टर के साथ विरासत श्रृंखला के नीचे सभी तरह से ISerializable लागू करना है?

नोट GetObjectData आभासी इसलिए व्युत्पन्न वर्ग को अपने खेतों को क्रमानुसार सकते हैं और फिर आधार वर्ग कहते हैं। यह काम करता है लेकिन यह कक्षाओं (100 के दशक) में बहुत कठिन काम करने का एक टन है।

कुछ व्युत्पन्न प्रकार (स्प्राइट, InvaderBehaviour, आदि) भी कस्टम क्रमांकन काम को मामले को बदतर बनाने के लिए।

मैं इस विषय पर जेफरी रिक्टर लेख में देखा है और एक ResourceSurrogateSelector का उपयोग कर की कोशिश की: बजाय ISerializationSurrogate प्रकार निर्माण लेकिन उन क्रमबद्धता तरीकों यदि प्रकार धारावाहिक की जा रही ही कहा जाता हो एक संसाधन है और एक प्रकार संसाधन से प्राप्त होता है (यानी होगा एक हमलावर या GameScreen)

क्यू) वहाँ यह करने के लिए एक स्मार्ट तरीका है serializing नहीं बुलाया हो सकते हैं?

मैंने दो कोड-बेस को एक-दूसरे के बहुत करीब रखने में कामयाब रहा है और इसने रूपांतरण को और अधिक आसान बना दिया है - मैं यहां इस दृष्टिकोण को जारी रखना चाहता हूं (इसलिए कोई XmlSerializer, Protobuf, आदि) जब तक कोई नहीं है वास्तव में अनिवार्य कारण नहीं है।

मैंने प्रक्रिया को स्वचालित करने के लिए कुछ जावा लिखने के बारे में सोचा है और सीरियलज़ेबल इंटरफेस को लागू करने वाले प्रकारों को प्रतिबिंबित करते हैं और सभी .NET क्रमबद्धता कोड के साथ एक .cs फ़ाइल बनाते हैं ताकि मैं मुख्य वर्ग फ़ाइलों को प्रदूषित न करूं (मैं उन्हें आंशिक बना दूंगा)

पीएस - लक्ष्य प्लेटफॉर्म विंडोज 8/सतह/एक्सबॉक्स 360 चीजों के नेट पक्ष (इसलिए संस्करण 4) और शायद पीएस वीटा/शायद आईओएस का उपयोग कर आईओएस पर होगा। बचाता है प्लेटफॉर्म पर deserialized वे serialized थे।

संपादित इस पोस्ट में सेर्गेई Teplyakov द्वारा एक उत्तर .... .NET, C#: How to add a custom serialization attribute that acts as ISerializable interface ... मेरे ISurrogateSelector इंटरफ़ेस जो है जैसे कि यह वांछित व्युत्पन्न वर्ग का चयन के साथ मदद मिलेगी लग रहा है के लिए प्रेरित किया।

उत्तर

1

यही वह है जो मैंने अभी तक आने में कामयाब रहा है और मैं इसके साथ बहुत खुश हूं :-) बस पढ़ने के लिए मिला/लिखने की जगह और मैं पूरा कर रहा हूं! (मैं शायद ऑब्जेक्ट, SerializationInfo लपेटूंगा, StreamingContext भी ऑब्जेक्टऑटपुटस्ट्रीम में अच्छी माप के लिए तर्क देता है)।

using System; 
using System.Diagnostics; 
using System.IO; 
using System.Reflection; 
using System.Runtime.Serialization; 
using System.Runtime.Serialization.Formatters.Binary; 

using java.io; //My implementation of various Java classes 

namespace NewSerializationTest { 

public sealed class JavaSerializableSurrogateSelector : ISurrogateSelector 
{ 
    public void ChainSelector(ISurrogateSelector selector) { throw new NotImplementedException(); } 

    public ISurrogateSelector GetNextSelector() { throw new NotImplementedException(); } 

    public ISerializationSurrogate GetSurrogate(Type type, StreamingContext context, out ISurrogateSelector selector) 
    { 
     if (typeof(Serializable).IsAssignableFrom(type)) 
     { 
      selector = this; 
      return new JavaSerializationSurrogate(); 
     } 

     //Type is not marked (java.io.)Serializable 
     selector = null; 
     return null; 
    } 
} 

public sealed class JavaSerializationSurrogate : ISerializationSurrogate { 

    //Method called to serialize a java.io.Serializable object 
    public void GetObjectData(Object obj, SerializationInfo info, StreamingContext context) { 

     //Do the entire tree looking for the 'marker' methods 
     var type = obj.GetType(); 
     while (type != null) 
     { 
      var writeObject = type.GetMethod("writeObject", BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.NonPublic, null, new Type[] { typeof(SerializationInfo), typeof(StreamingContext), typeof(Type) }, null); 
      if (writeObject != null) { 
       //Class has declared custom serialization so call through to that 
       writeObject.Invoke(obj, new object[] { info, context, type }); 
      } else { 
       //Default serialization of all non-transient fields at this level only (not the entire tree) 
       obj.SerializeFields(info, context, type); 
      } 

      type = type.BaseType; 
     } 
    } 

    //Method called to deserialize a java.io.Serializable object 
    public Object SetObjectData(Object obj, SerializationInfo info, StreamingContext context, ISurrogateSelector selector) { 

     //Do the entire tree looking for the 'marker' methods 
     var type = obj.GetType(); 
     while (type != null) 
     { 
      var readObject = type.GetMethod("readObject", BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.NonPublic, null, new Type[] { typeof(SerializationInfo), typeof(StreamingContext), typeof(Type) }, null); 
      if (readObject != null) { 
       //Class has declared custom serialization so call through to that 
       readObject.Invoke(obj, new object[] { info, context, type }); 
      } else { 
       //Default serialization of all non-transient fields at this level only (not the entire tree) 
       obj.DeserializeFields(info, context, type); 
      } 

      type = type.BaseType; 
     } 

     return null; 
    } 
} 

[Serializable] 
class A : java.io.Serializable { 
    public string Field1; 
} 

[Serializable] 
class B : A { 
    public string Field2; 

    private void readObject(SerializationInfo stream, StreamingContext context, Type declaringType) { 
     stream.defaultReadObject(context, this, declaringType); 

     Debug.WriteLine("B: readObject"); 
    } 

    private void writeObject(SerializationInfo stream, StreamingContext context, Type declaringType) { 
     stream.defaultWriteObject(context, this, declaringType); 

     Debug.WriteLine("B: writeObject"); 
    } 
} 

[Serializable] 
class C: B { 
    public string Field3; 

    private void writeObject(SerializationInfo stream, StreamingContext context, Type declaringType) { 
     stream.defaultWriteObject(context, this, declaringType); 

     Debug.WriteLine("C: writeObject"); 
    } 
} 

public static class SerializationInfoExtensions { 

    public static void defaultWriteObject(this SerializationInfo info, StreamingContext context, object o, Type declaringType) { 
     o.SerializeFields(info, context, declaringType); 
    } 

    public static void defaultReadObject(this SerializationInfo info, StreamingContext context, object o, Type declaringType) { 
     o.DeserializeFields(info, context, declaringType); 
    } 
} 

class Program { 
    static void Main(string[] args) { 

     var myC = new C { Field1 = "tom", Field2 = "dick", Field3 = "harry" }; 

     using (var ms = new MemoryStream()) { 
      var binaryFormatter = new BinaryFormatter(); 
      binaryFormatter.SurrogateSelector = new JavaSerializableSurrogateSelector(); 

      binaryFormatter.Serialize(ms, myC); 
      ms.Position = 0; 
      var myCDeserialized = binaryFormatter.Deserialize(ms); 
     } 
    } 
} 

/// <summary> 
/// Extensions to the object class. 
/// </summary> 
public static class ObjectExtensions 
{ 
    /// <summary> 
    /// Serializes an object's class fields. 
    /// </summary> 
    /// <param name="source">The source object to serialize.</param> 
    /// <param name="info">SerializationInfo.</param> 
    /// <param name="context">StreamingContext.</param> 
    /// <param name="declaringType">The level in the inheritance whose fields are to be serialized - pass null to serialize the entire tree.</param> 
    public static void SerializeFields(this object source, SerializationInfo info, StreamingContext context, Type declaringType) 
    { 
     //Serialize the entire inheritance tree if there is no declaringType passed. 
     var serializeTree = declaringType == null; 

     //Set the level in the class heirarchy we are interested in - if there is no declaring type use the source type (and the entire tree will be done). 
     var targetType = declaringType ?? source.GetType(); 

     //Get the set of serializable members for the target type 
     var memberInfos = FormatterServices.GetSerializableMembers(targetType, context); 

     // Serialize the base class's fields to the info object 
     foreach (var mi in memberInfos) 
     { 
      if (serializeTree || mi.DeclaringType == targetType) { 
       //Specify the name to use as the key - if the entire tree is being done then the names will already have a prefix. Otherwise, we need to 
       //append the name of the declaring type. 
       var name = serializeTree ? mi.Name : mi.DeclaringType.Name + "$" + mi.Name; 

       info.AddValue(name, ((FieldInfo)mi).GetValue(source)); 
      } 
     } 
    } 

    /// <summary> 
    /// Deserializes an object's fields. 
    /// </summary> 
    /// <param name="source">The source object to serialize.</param> 
    /// <param name="info">SerializationInfo.</param> 
    /// <param name="context">StreamingContext.</param> 
    /// <param name="declaringType">The level in the inheritance whose fields are to be deserialized - pass null to deserialize the entire tree.</param> 
    public static void DeserializeFields(this object source, SerializationInfo info, StreamingContext context, Type declaringType) 
    { 
     //Deserialize the entire inheritance tree if there is no declaringType passed. 
     var deserializeTree = declaringType == null; 

     //Set the level in the class heirarchy we are interested in - if there is no declaring type use the source type (and the entire tree will be done). 
     var targetType = declaringType ?? source.GetType(); 

     var memberInfos = FormatterServices.GetSerializableMembers(targetType, context); 

     // Deserialize the base class's fields from the info object 
     foreach (var mi in memberInfos) 
     { 
      //Only serialize the fields at the specific level requested. 
      if (deserializeTree || mi.DeclaringType == declaringType) 
      { 
       // To ease coding, treat the member as a FieldInfo object 
       var fi = (FieldInfo) mi; 

       //Specify the name to use as the key - if the entire tree is being done then the names will already have a prefix. Otherwise, we need to 
       //append the name of the declaring type. 
       var name = deserializeTree ? mi.Name : mi.DeclaringType.Name + "$" + mi.Name; 

       // Set the field to the deserialized value 
       fi.SetValue(source, info.GetValue(name, fi.FieldType)); 
      } 
     } 
    } 
} 
} 
संबंधित मुद्दे