예제 #1
0
        /// <summary>
        /// 指定ストリームの現在位置から受信する再帰ループ
        /// </summary>
        /// <param name="reader">ストリーム</param>
        /// <returns>インスタンス化されたオブジェクト</returns>
        private static object receiveLoop(Stream reader)
        {
            object ret          = null;
            Type   subClassType = null;

            for (var isLoop = true; isLoop;)
            {
                var  tag = (Tag)reader.ReadByte();
                Type currentType;
                switch (tag)
                {
                case Tag.ClassStart:
                {
                    // クラスを特定する = currentType = subClassType
                    ReceiveDirect(reader, out int classid);             // クラスを特定する = currentType = subClassType

                    var keystr = NamedId.FromIDNoName(classid).Name;
                    var keys   = keystr.Split(new char[] { '/' });
                    System.Diagnostics.Debug.Assert(keys.Length == 4, "シリアライズClass IDが不正でした");

                    // クラスのインスタンスを生成する = ret
                    currentType = Type.GetType(keys[2]);
                    if (currentType == null)
                    {
                        var hInst = Activator.CreateInstance(keys[3], keys[2]);
                        ret         = hInst.Unwrap();
                        currentType = ret.GetType();
                    }
                    else
                    {
                        ret = Activator.CreateInstance(currentType, true);
                    }
                    subClassType = currentType;
                    break;
                }

                case Tag.SubClass:
                {
                    // サブクラスを特定する = subClassType
                    ReceiveDirect(reader, out                                 // サブクラスを特定する = subClassType
                                  int classid);
                    var keystr = NamedId.FromIDNoName(classid).Name;
                    var keys   = keystr.Split(new char[] { '/' });
                    System.Diagnostics.Debug.Assert(keys.Length == 4, "シリアライズClass IDが不正でした");

                    subClassType = Type.GetType(keys[2] + ", " + keys[3]);
                    break;
                }

                case Tag.Field:
                {
                    // フィールドを特定する = fi
                    ReceiveDirect(reader, out                                 // フィールドを特定する = fi
                                  int fieldid);
                    var keystr = NamedId.FromIDNoName(fieldid).Name;
                    var keys   = keystr.Split(new char[] { '/' });
                    System.Diagnostics.Debug.Assert(keys.Length == 4, "シリアライズField IDが不正でした");
                    var fi = subClassType.GetField(keys[2 /*field名*/], BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

                    // フィールドの値を取得する(再帰コール)
                    var fieldValue = receiveLoop(reader);

                    // フィールドの値をインスタンスに設定する
                    fi.SetValue(ret, fieldValue);
                    break;
                }

                case Tag.Null:
                {
                    return(null);
                }

                case Tag.List:
                {
                    ReceiveDirect(reader, out int classid);
                    var keystr = NamedId.FromIDNoName(classid).Name;
                    var keys   = keystr.Split(new char[] { '/' });
                    System.Diagnostics.Debug.Assert(keys.Length == 4, "シリアライズClass IDが不正でした");

                    // クラスのインスタンスを生成する = ret
                    currentType = Type.GetType(keys[2]);
                    if (currentType == null)
                    {
                        var hInst = Activator.CreateInstance(keys[3], keys[2]);
                        ret         = hInst.Unwrap();
                        currentType = ret.GetType();
                    }
                    else
                    {
                        ret = Activator.CreateInstance(currentType, true);
                    }

                    // 配列数を取得す
                    ReceiveDirect(reader, out
                                  // 配列数を取得す
                                  int n);

                    for (var i = 0; i < n; i++)
                    {
                        // 各要素の値を取得する(再帰コール)
                        var val = receiveLoop(reader);
                        ((IList)ret).Add(val);
                    }
                    // サブクラスのために準備する
                    subClassType = currentType;
                    break;
                }

                case Tag.Dictionary:
                {
                    ReceiveDirect(reader, out int classid);
                    var keystr = NamedId.FromIDNoName(classid).Name;
                    var keys   = keystr.Split(new char[] { '/' });
                    System.Diagnostics.Debug.Assert(keys.Length == 4, "シリアライズClass IDが不正でした");

                    // クラスのインスタンスを生成する = ret
                    currentType = Type.GetType(keys[2]);
                    if (currentType == null)
                    {
                        var hInst = Activator.CreateInstance(keys[3], keys[2]);
                        ret         = hInst.Unwrap();
                        currentType = ret.GetType();
                    }
                    else
                    {
                        ret = Activator.CreateInstance(currentType, true);
                    }

                    // 配列数を取得す
                    ReceiveDirect(reader, out
                                  // 配列数を取得す
                                  int n);

                    for (var i = 0; i < n; i++)
                    {
                        // 各要素の値を取得する(再帰コール)
                        var key = receiveLoop(reader);
                        var val = receiveLoop(reader);
                        ((IDictionary)ret).Add(key, val);
                    }
                    // サブクラスのために準備する
                    subClassType = currentType;
                    break;
                }

                case Tag.ClassEnd:
                {
                    receiveFinalize(ret);
                    return(ret);
                }

                case Tag.vString:
                {
                    ReceiveDirect(reader, out string s);
                    return(s);
                }

                default:
                {
                    var valType  = (Type)_tagToType[tag];
                    var valTypeR = valType.Assembly.GetType(valType.ToString() + "&");
                    ret = Activator.CreateInstance(valType);
                    var types = new Type[] { typeof(Stream), valTypeR };
                    var mi    = typeof(SerializerEx).GetMethod("ReceiveDirect", types);
                    ret = mi.Invoke(null, new object[] { reader, ret });
                    receiveFinalize(ret);
                    return(ret);
                }
                }
            }
            receiveFinalize(ret);
            return(ret);
        }