Вопрос

Возможно, я что -то упускаю, но я пытаюсь бороться с буферами протокола в простом методе для предоставления расширений позже. Это кажется немного неясным, поэтому я перейду прямо в проблему.

Я пишу сборку для поддержки различных задач, одна из которых включает описание структурированных данных. Идеальное время для использования буферов протокола. Первичный класс для использования буферов протокола называется SpecatedEfinition. Вот файл .proto, который я придумал для этого:

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)

Моя цель состояла в том, чтобы позволить этим _statedef -сообщениям быть расширены позже, какие поля, которые он понадобится. Тем не менее, это расширение произойдет независимо от библиотеки, которую я сейчас пишу.

Kagents.dll -> обрабатывает определение определения и тому подобное.

Что -то, ссылаясь на kagents.dll -> имеет файл Protobuff с «Extend GraphicsStedef», чтобы определить необходимое состояние.

Я надеялся, что определение «Extend GraphicsStatedef» генерирует код, который позволит мне использовать свойства для доступа к этим полям, и избежать громоздкого «Extendible.appendValue ()» и getValue () синтаксиса.

Одно решение, которое я разработал, что кажется хакерским, состоит в том, чтобы определить класс в ссылке DLL с помощью методов расширения, например, так:

    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);
        }
    }

Если кто -то сможет придумать лучшего способа, я был бы очень обязан. =) Кроме того, я не уверен, насколько ясным мое описание проблемы вышло, поэтому, если есть какие -либо разъяснения или дополнительную информацию, которую я могу предоставить, дайте мне знать. знак равно

РЕДАКТИРОВАТЬ: Итак, многое подумали об этом и понял, что я неправильно подхожу к проблеме. SateReerence должен хранить список разных игровых центров. Кроме того, он хранит заявленное определение, которое должно описать состояние данного состояния. В настоящее время я пытаюсь десериализовать буферы состояния в разные классы (Graphicsstatedef), когда я действительно должен пускать в сами объекты состояния.

Следовательно, мне нужно переосмыслить дизайн так, что заявление становятся контейнером для потока и извлекает только достаточное количество информации для поля «Повторные статипы обязательств = 1». Затем, в сборе ссылки, остальная часть потока может быть опустошен в соответствующие состояния.

У кого -нибудь есть рекомендации о том, как подходить к этому? Несколько идей формулируют, но ничего конкретного, и я бы хотел вклад других.

Это было полезно?

Решение 2

Окончательный ответ:

Хорошо, поэтому, несколько дней назад, я остановился на решении, и я просто обновляю это, если кто -то еще столкнется с той же проблемой.

Вся проблема вызвана тем фактом, что я не осознавал, что Protobuf-Net может поддерживать байт []. Итак, вот мое решение:

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

Другие советы

Я автор Protobuf-Net. Я ничего не добавил, чтобы рассмотреть сценарий, как представлено непосредственно (кроме Extensible Код), но я открыт для предложения о том, что вы думаете должен делать.

Мне также нужно было бы проверить, позволяет ли «проток» (компилятор .proto, который я использую для анализа .proto до генерации кода) различать регулярные и расширенные члены.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top