Sto convertendo un gioco Java in C# (Titan Attacks di Puppy Games) e sono praticamente finito ora a parte l'ultimo compito che è la serializzazione dello stato del gioco per salvare i file.. Serializzazione net - mixing [Serializable] con albero di ereditarietà personalizzato
gerarchia tipica: Resource (base) -> Feature-> Schermo/Effetto/entity> GameScreen/LaserEffect/Invader
Il codice Java utilizza lo standard ObjectOutputStream/ObjectInputStream per eseguire la serializzazione binaria ma esegue fastidiosamente alcuni readResolve/writeResolve funziona a livello di classe base (Risorsa) per personalizzare il processo di serializzazione (se una risorsa è denominata, non la serializza e semplicemente restituisce un proxy con un nome che viene utilizzato in seguito per estrarre la risorsa da una hashmap).
mie soluzioni ingenuo è quello di copiare ciecamente questo approccio e implementare ISerializable nella classe di base per ignorare l'TYPE ...
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));
}
D) Quindi, sono abbastanza sicuro che tutte le scommesse sono spenti per built -in serializzazione e devo implementare ISerializable fino in fondo la catena di ereditarietà con il costruttore di serializzazione?
Nota GetObjectData è virtuale in modo che le classi derivate possano serializzare i loro campi e quindi chiamare la classe base. Questo funziona, ma è un sacco di lavoro noioso che aggiunge a molte classi (100).
Alcuni tipi derivati (Sprite, InvaderBehaviour, ecc.) Eseguono anche operazioni di serializzazione personalizzate per peggiorare le cose.
Ho esaminato gli articoli di Jeffrey Richter sull'argomento e ho provato a utilizzare un costrutto di tipo ResourceSurrogateSelector: ISerializationSurrogate, ma questi metodi di serializzazione vengono richiamati solo se il tipo serializzato è una risorsa e non un tipo derivato da una risorsa (ad es. non viene chiamato serializzare un Invader o GameScreen)
Q) c'è un modo intelligente per farlo?
Sono riuscito a mantenere le due basi di codice molto vicine tra loro e questo ha reso la conversione molto più semplice - Mi piacerebbe continuare questo approccio qui (quindi senza XmlSerializer, Protobuf, ecc.) A meno che non ci sia un ragione molto convincente per non farlo.
Ho pensato di scrivere un po 'di Java per automatizzare il processo e riflettere i tipi che implementano l'interfaccia Serializable e creare un file .cs con tutto il codice di serializzazione .Net in modo da non inquinare i file di classe principale (Li renderei parziali)
PS - Le piattaforme di destinazione saranno Windows8/Surface/XBox360 sul lato .Net delle cose (quindi versione 4) e probabilmente PS Vita/forse iOS che utilizza Mono. I salvataggi sono deserializzati sulla piattaforma su cui sono stati serializzati.
EDIT Una risposta da Sergey Teplyakov in questo post .... .NET, C#: How to add a custom serialization attribute that acts as ISerializable interface ... mi ha portato all'interfaccia ISurrogateSelector che sembra che vi aiuterà con la selezione delle classi derivate desiderati.