質問

私はおそらく何かを見落としていますが、後で拡張機能を提供するための簡単な方法にプロトコルバッファーを格闘しようとしています。それは少し不明のように思えますので、私は問題に直接飛び込みます。

私は、構造化されたデータの説明を含むさまざまなタスクをサポートするためにアセンブリを作成しています。プロトコルバッファーを使用するのに最適な時期。プロトコルバッファーを使用するプライマリクラスは、Statedefinitionと呼ばれます。これが私がそれのために思いついた.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-> Statedefinitionの解析などを処理します。

kagents.dll->を参照するものには、必要な状態を定義するために「拡張グラフィックステレジーズ」を備えたプロトバフファイルがあります。

「拡張グラフィックステレジーズ」を定義することで、プロパティを使用してこれらのフィールドにアクセスできるコードを生成し、面倒な「extendible.AppendValue()」とgetValue()Syntaxを避けることを望んでいました。

私が考案した1つのソリューションは、ハッキッシュのように見えますが、次のような拡張メソッドを使用して、参照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);
        }
    }

誰かがより良い方法を考えることができれば、私は多くの義務を負うでしょう。 =)また、問題の説明がどのように明らかになったかはわかりませんので、明確化や詳細情報が提供できる場合は、お知らせください。 =)

編集:それで、これについて多くのことを考えて、問題に間違っていることに気付いた後。統計は、異なるGamestateのリストを保存することになっています。同様に、この州の参照の状態を説明する必要があるStatedefinitionを保存します。現在、私は状態バッファーをさまざまなクラス(GraphicsStatedef)に脱着しようとしています。

したがって、StateDefinitionがストリームのコンテナになり、「Repeated StateTypes requiredStates = 1」フィールドに十分な情報のみを抽出するように設計を再考する必要があります。次に、参照アセンブリでは、ストリームの残りの部分をそれぞれの状態に偏りにすることができます。

誰かがこれにアプローチする方法についてのお勧めを持っていますか?いくつかのアイデアが定式化されていますが、具体的なものはありません。他の人の入力が大好きです。

役に立ちましたか?

解決 2

Final answer:

Alright, so, A few days ago I settled on a solution and I'm just updating this in case anyone else runs into the same issue.

The whole problem stemmed from the fact that I didn't realize protobuf-net could support byte[]. So, here's my solution:

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 コード)、しかし私はあなたがそれをどう思うかについての提案を受け入れています したほうがいい 行う。

また、「Protoc」(コード生成の前に.roproを解析するために使用する.roproコンパイラ)により、通常のメンバーと拡張メンバーを区別できるかどうかを確認する必要があります。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top