Domanda

Sono forse si affaccia qualcosa, ma sto cercando di lottare buffer di protocollo in un metodo semplice per fornire le estensioni più tardi. Che sembra un po 'poco chiaro quindi mi butto direttamente nel problema.

Le scrivo un'assemblea per sostenere le varie operazioni, una delle quali include la descrizione di dati strutturati. momento ideale per utilizzare i buffer di protocollo. La classe principale di utilizzare i buffer di protocollo si chiama StateDefinition. Ecco il file Proto mi si avvicinò con per esso:

package Kannon.State;
message StateDefinition {
    enum StateTypes {
        GRAPHICS = 0;
        AUDIO = 1;
        MIND = 2;
        PHYSICS = 3;
        NETWORK = 4;
        GENERIC = 5;
    }
    repeated StateTypes requiredStates = 1; 
    optional GraphicsStateDef Graphics = 2;
    optional AudioStateDef Audio = 3;
         (etc)
}

message GraphicsStateDef {
    extensions 100 to max;
}

message AudioStateDef {
    extensions 100 to max;
}
    (etc)

Il mio obiettivo era quello di permettere quei messaggi _StateDef di essere esteso in seguito con quello che il campo sarebbe bisogno. Tuttavia, questa estensione sarebbe accaduto indipendente dalla biblioteca Attualmente sto scrivendo.

Kagents.dll ->     Maniglie StateDefinition analisi e così via.

Qualcosa Referencing Kagents.dll ->     Ha un file protobuff con "estendere GraphicsStateDef" per definire lo stato aveva bisogno.

Speravo che definisce la sintassi "estendere GraphicsStateDef" genererebbe codice che mi avrebbe permesso di utilizzare le proprietà per accedere a questi campi, e di evitare l'ingombrante "Extendible.AppendValue ()" e GetValue ().

Una soluzione ho ideato, che sembra hacker, è quello di definire una classe nella DLL di riferimento con metodi di estensione, in questo modo:

    public static class GraphicsExt
    {
        enum Fields
        {
            someValue = 1,
            someOtherValue = 2
        }

        public static Int32 someValue(this State.GraphicsStateDef def)
        {
            return Extensible.GetValue(def, Fields.someValue);
        }
        public static void someValue(this State.graphicsStateDef def, Int32 value)
        {
            Extensible.AppendValue(def, fields.someValue, value);
        }
    }

Se qualcuno può pensare a un modo migliore, sarei molto grato. =) Inoltre, io non sono sicuro di come la mia lucida descrizione del problema è venuto fuori, quindi se c'è qualsiasi chiarimento o ulteriori informazioni posso fornire, per favore fatemelo sapere. =)

EDIT: Così, dopo aver pensato molto a questo e realizzato sto avvicinando il problema sbagliato. StateReference si suppone per memorizzare un elenco di diversi gamestate di. Pure, memorizza una StateDefinition, che dovrebbe descrivere lo stato di questo riferimento stato. Attualmente, sto cercando di deserializzare i buffer di stato in diverse classi (GraphicsStateDef), quando in realtà dovrebbe essere deserializzazione nello stato stessi oggetti.

Per questo, ho bisogno di ripensare il progetto in modo tale che StateDefinition diventa un contenitore per il flusso ed estrae solo le informazioni sufficienti per il campo "ripetuto StateTypes requiredStates = 1". Poi, nel montaggio di riferimento, il resto del flusso può essere deserializzato nei rispettivi stati.

Qualcuno ha consigli utili su come affrontare questo? Alcune idee stanno formulando, ma nulla di concreto, e mi piacerebbe l'ingresso degli altri.

È stato utile?

Soluzione 2

Risposta finale:

Bene, così, pochi giorni fa ho optato per una soluzione e io sono solo l'aggiornamento di questo nel caso in cui nessun altro corre lo stesso problema.

L'intero problema derivava dal fatto che non mi rendevo conto protobuf-net potrebbe sostenere byte []. Quindi, ecco la mia soluzione:

namespace Kannon.State
{
    /// <summary>
    /// ReferenceDefinition describes the layout of the reference in general.
    /// It tells what states it should have, and stores the stream buffers for later serialization.
    /// </summary>
    [ProtoBuf.ProtoContract]
    public class ReferenceDefinition
    {
        /// <summary>
        /// There are several built in state types, as well as rudimentary support for a "Generic" state.
        /// </summary>
        public enum StateType
        {
            Graphics=0,
            Audio,
            Mind,
            Physics,
            Network,
            Generic
        }

        /// <summary>
        /// Represents what states should be present in the ReferenceDefinition
        /// </summary>
        [ProtoBuf.ProtoMember(1)]
        List<StateType> m_StatesPresent = new List<StateType>();

        /// <summary>
        /// Represent a list of StateDefinitions, which hold the buffers for each different type of state.
        /// </summary>
        [ProtoBuf.ProtoMember(2)]
        List<StateDefinition> m_StateDefinition = new List<StateDefinition>();

        /// <summary>
        /// Add a state, mapped to a type, to this reference definition.
        /// </summary>
        /// <param name="type">Type of state to add</param>
        /// <param name="def">State definition to add.</param>
        public void AddState(StateType type, StateDefinition def)
        {
            // Enforce only 1 of each type, except for Generic, which can have as many as it wants.
            if (m_StatesPresent.Contains(type) && type != StateType.Generic)
                return;
            m_StatesPresent.Add(type);
            m_StateDefinition.Add(def);
        }
    }

    /// <summary>
    /// Represents a definition of some gamestate, storing protobuffered data to be remapped to the state.
    /// </summary>
    [ProtoBuf.ProtoContract]
    public class StateDefinition
    {
        /// <summary>
        /// Name of the state
        /// </summary>
        [ProtoBuf.ProtoMember(1)]
        string m_StateName;
        /// <summary>
        /// Byte array to store the "data" for later serialization.
        /// </summary>
        [ProtoBuf.ProtoMember(2)]
        byte[] m_Buffer;

        /// <summary>
        /// Constructor for the state definition, protected to enforce the Pack and Unpack functionality to keep things safe.
        /// </summary>
        /// <param name="name">Name of the state type.</param>
        /// <param name="buff">byte buffer to build state off of</param>
        protected StateDefinition(String name, byte[] buff)
        {
            m_StateName = name;
            m_Buffer = buff;
        }

        /// <summary>
        /// Unpack a StateDefinition into a GameState
        /// </summary>
        /// <typeparam name="T">Gamestate type to unpack into.  Must define Protobuf Contracts.</typeparam>
        /// <param name="def">State Definition to unpack.</param>
        /// <returns>The unpacked state data.</returns>
        public static T Unpack<T>(StateDefinition def) where T:GameState
        {
            // Make sure we're unpacking into the right state type.
            if (typeof(T).Name == def.m_StateName)
                return ProtoBuf.Serializer.Deserialize<T>(new MemoryStream(def.m_Buffer));
            else
                // Otherwise, return the equivalent of Null.
                return default(T);
        }

        /// <summary>
        /// Pack a state type into a State Definition
        /// </summary>
        /// <typeparam name="T">Gamestate to package up.  Upst define protobuf contracts.</typeparam>
        /// <param name="state">State to pack up.</param>
        /// <returns>A state definition serialized from the passed in state.</returns>
        public static StateDefinition Pack<T>(T state) where T:GameState
        {
            // Using a memory stream, to make sure Garbage Collection knows what's going on.
            using (MemoryStream s = new MemoryStream())
            {
                ProtoBuf.Serializer.Serialize<T>(s, state);
                // Uses typeof(T).Name to do semi-enforcement of type safety.  Not the best, but it works.
                return new StateDefinition(typeof(T).Name, s.ToArray());
            }
        }
    }
}

Altri suggerimenti

Sono l'autore di protobuf-net. Io non ho aggiunto nulla per affrontare lo scenario presentato come direttamente (diverso il codice Extensible), ma sono aperti a suggerimenti su ciò che si pensa che dovrebbe fare.

Vorrei anche bisogno di controllare se "ProtoC" (il compilatore Proto che uso per analizzare Proto prima generazione di codice) mi permette di distinguere tra i membri regolari e prolungati.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top