سؤال

أنا ربما يطل على شيء ما، لكنني أحاول تصارع المخازن المؤقتة في البروتوكول في طريقة سهلة لتوفير الملحقات في وقت لاحق. يبدو أن هذا غير واضح بعض الشيء، لذا سأقفز مباشرة إلى المشكلة.

أكتب جمعية لدعم المهام المختلفة، والتي تتضمن واحدة منها وصف البيانات المنظمة. الوقت المثالي لاستخدام المخازن المؤقتة بروتوكول. يسمى الطبقة الأساسية لاستخدام مخازن البروتوكول المخزن المؤقتين. هنا ملف. بروتو وصلت معه:

حزمة kannon.state؛ رسالة STATEDEFINITIENITIE {ENUM StateTypes {Graphics = 0؛ الصوت = 1؛ العقل = 2؛ الفيزياء = 3؛ الشبكة = 4؛ عام = 5؛ } تتاحت الحملات المتكررة = 1؛ الرسومات الاختيارية الرسومات = 2؛ Audiostatedef اختياري = 3؛ (إلخ)} رسالة رسومات الصفحةStedEf {ملحقات 100 إلى الحد الأقصى؛ } رسالة Audiostatedef {ملحقات 100 إلى ماكس؛ } (إلخ)

كان هدفي هو السماح بتمديد رسائل تلك _StatedEF لاحقا بما يحتاجه الحقول التي ستحتاج إليها. ومع ذلك، سيحدث هذا التمديد مستقلا عن المكتبة التي أكتبها حاليا.

kagents.dll -> يتعامل مع تحليل المشار إليها ومثلها.

هناك شيء مراجع Kagents.dll -> لديه ملف Protobuff مع "تمديد GraphicsstateDef" لتحديد الحالة اللازمة.

كنت آمل أن يؤدي تحديد "توسيع graphicstatedeatef" إلى إنشاء رمز يسمح لي باستخدام خصائص للوصول إلى هذه الحقول، وتجنب بناء جملة بناء الجملة و GetValue مرهقة ().

أحد الحلول التي ابتدوها، والتي تبدو تتبع، هي تحديد فئة في DLL المرجعية مع طرق التمديد، مثل ذلك:

 Public Static Class Graphicsext {Ink Fields {somevalue = 1، someothervalue = 2} public static int32 somvalue (this state.graphicsstatedef def) {إرجاع extensible.getValue (def، fields.somevalue)؛ } Public Satic Void Somevalue (هذه الحالة. graphicsstatedeef def، INT32 القيمة) {extensible.appendvalue (def، fields.somevalue، القيمة)؛ }}

إذا كان أي شخص يمكن أن يفكر في طريقة أفضل، سأكون ملزما كثيرا. =) أيضا، لست متأكدا من كيفية خروج الوصف الخاص بي للمشكلة، لذلك إذا كان هناك أي توضيح أو مزيد من المعلومات يمكنني تقديمه، واسمحوا لي أن أعرف. =)

تحرير: إذن، بعد التفكير كثيرا حول هذا وأدركت أنني أقترب من مشكلة الخطأ. من المفترض أن يخزن STATITILLERIVER للحصول على قائمة بمختلف gamestate. كذلك، فإنها تخزن مذكرات تعريف، يجب أن تصف حالة مرجع الدولة هذه. في الوقت الحالي، أحاول أن أرغز المخازن المؤقتة للدولة في فصول مختلفة (GraphicsStedEdatedef)، عندما أكون حقا يجب أن أكون هارما في كائنات الدولة نفسها.

لذلك، أحتاج إلى إعادة التفكير في التصميم بحيث يصبح هذا المحرف حاوية للدفق واستخراج معلومات كافية فقط للحصول على حقل "StatesTypes المتكررة المطلوبة = 1". ثم، في الجمعية المرجعية، يمكن أن يكون بقية الدفق تجارية في الدول المعنية.

هل يحصل أي شخص على كيفية التعامل مع هذا؟ بعض الأفكار صياغة، ولكن لا شيء ملموس، وأحب مدخلات الآخرين.

هل كانت مفيدة؟

المحلول 2

الجواب النهائي:

حسنا، لذلك، قبل بضعة أيام استقرت على حل وأنا مجرد تحديث هذا في حالة تشغيل أي شخص آخر في نفس المشكلة.

المشكلة برمتها تنبع من حقيقة أنني لم أكن أدرك صافي Protobuf - يمكن أن يدعم البايت []. لذلك، ها هو الحل الخاص بي:

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 قبل جيل التعليمات البرمجية) يتيح لي التمييز بين الأعضاء العاديين والموسعين.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top