public static object ReadMethodResponse(BinaryElement elem, BinaryReader reader, bool hasHeaders, HeaderHandler headerHandler, IMethodCallMessage methodCallMessage, BinaryFormatter formatter)
        {
            if (elem != BinaryElement.MethodResponse)
            {
                throw new SerializationException("Invalid format. Expected BinaryElement.MethodResponse, found " + elem);
            }

            MethodFlags   flags          = (MethodFlags)reader.ReadByte();
            ReturnTypeTag typeTag        = (ReturnTypeTag)reader.ReadByte();
            bool          hasContextInfo = (flags & MethodFlags.IncludesLogicalCallContext) > 0;

            // FIXME: find a meaning for those 2 bytes
            reader.ReadByte();
            reader.ReadByte();

            object returnValue = null;

            object[]           outArgs     = null;
            LogicalCallContext callContext = null;
            Exception          exception   = null;

            object[] extraProperties = null;
            Header[] headers         = null;

            if ((typeTag & ReturnTypeTag.PrimitiveType) > 0)
            {
                Type type = BinaryCommon.GetTypeFromCode(reader.ReadByte());
                returnValue = ObjectReader.ReadPrimitiveTypeValue(reader, type);
            }

            if ((flags & MethodFlags.PrimitiveArguments) > 0)
            {
                uint count = reader.ReadUInt32();
                outArgs = new object[count];
                for (int n = 0; n < count; n++)
                {
                    Type type = BinaryCommon.GetTypeFromCode(reader.ReadByte());
                    outArgs[n] = ObjectReader.ReadPrimitiveTypeValue(reader, type);
                }
            }

            if (hasContextInfo || (typeTag & ReturnTypeTag.ObjectType) > 0 ||
                (typeTag & ReturnTypeTag.Exception) > 0 ||
                (flags & MethodFlags.ArgumentsInSimpleArray) > 0 ||
                (flags & MethodFlags.ArgumentsInMultiArray) > 0)
            {
                // There objects that need to be deserialized using an ObjectReader

                ObjectReader objectReader = new ObjectReader(formatter);
                object       result;
                objectReader.ReadObjectGraph(reader, hasHeaders, out result, out headers);
                object[] msgInfo = (object[])result;

                if ((typeTag & ReturnTypeTag.Exception) > 0)
                {
                    exception = (Exception)msgInfo[0];
                    if (hasContextInfo)
                    {
                        callContext = (LogicalCallContext)msgInfo[1];
                    }
                }
                else if ((flags & MethodFlags.NoArguments) > 0 || (flags & MethodFlags.PrimitiveArguments) > 0)
                {
                    int n = 0;
                    if ((typeTag & ReturnTypeTag.ObjectType) > 0)
                    {
                        returnValue = msgInfo [n++];
                    }
                    if (hasContextInfo)
                    {
                        callContext = (LogicalCallContext)msgInfo[n++];
                    }
                    if (n < msgInfo.Length)
                    {
                        extraProperties = (object[])msgInfo[n];
                    }
                }
                else if ((flags & MethodFlags.ArgumentsInSimpleArray) > 0)
                {
                    outArgs = msgInfo;
                }
                else
                {
                    int n = 0;
                    outArgs = (object[])msgInfo[n++];
                    if ((typeTag & ReturnTypeTag.ObjectType) > 0)
                    {
                        returnValue = msgInfo[n++];
                    }
                    if (hasContextInfo)
                    {
                        callContext = (LogicalCallContext)msgInfo[n++];
                    }
                    if (n < msgInfo.Length)
                    {
                        extraProperties = (object[])msgInfo[n];
                    }
                }
            }
            else
            {
                reader.ReadByte(); // Reads the stream ender
            }

            if (headerHandler != null)
            {
                headerHandler(headers);
            }

            if (exception != null)
            {
                return(new ReturnMessage(exception, methodCallMessage));
            }
            else
            {
                int           argCount = (outArgs != null) ? outArgs.Length : 0;
                ReturnMessage result   = new ReturnMessage(returnValue, outArgs, argCount, callContext, methodCallMessage);

                if (extraProperties != null)
                {
                    foreach (DictionaryEntry entry in extraProperties)
                    {
                        result.Properties [(string)entry.Key] = entry.Value;
                    }
                }

                return(result);
            }
        }
        public static object ReadMethodResponse(BinaryElement elem, BinaryReader reader, bool hasHeaders, HeaderHandler headerHandler, IMethodCallMessage methodCallMessage, BinaryFormatter formatter)
        {
            if (elem != BinaryElement.MethodResponse)
            {
                throw new SerializationException("Invalid format. Expected BinaryElement.MethodResponse, found " + elem);
            }
            MethodFlags   methodFlags   = (MethodFlags)reader.ReadByte();
            ReturnTypeTag returnTypeTag = (ReturnTypeTag)reader.ReadByte();
            bool          flag          = (methodFlags & MethodFlags.IncludesLogicalCallContext) > (MethodFlags)0;

            reader.ReadByte();
            reader.ReadByte();
            object ret = null;

            object[]           array   = null;
            LogicalCallContext callCtx = null;
            Exception          ex      = null;

            object[] array2  = null;
            Header[] headers = null;
            if ((byte)(returnTypeTag & ReturnTypeTag.PrimitiveType) > 0)
            {
                Type typeFromCode = BinaryCommon.GetTypeFromCode((int)reader.ReadByte());
                ret = ObjectReader.ReadPrimitiveTypeValue(reader, typeFromCode);
            }
            if ((methodFlags & MethodFlags.PrimitiveArguments) > (MethodFlags)0)
            {
                uint num = reader.ReadUInt32();
                array = new object[num];
                int num2 = 0;
                while ((long)num2 < (long)((ulong)num))
                {
                    Type typeFromCode2 = BinaryCommon.GetTypeFromCode((int)reader.ReadByte());
                    array[num2] = ObjectReader.ReadPrimitiveTypeValue(reader, typeFromCode2);
                    num2++;
                }
            }
            if (flag || (byte)(returnTypeTag & ReturnTypeTag.ObjectType) > 0 || (byte)(returnTypeTag & ReturnTypeTag.Exception) > 0 || (methodFlags & MethodFlags.ArgumentsInSimpleArray) > (MethodFlags)0 || (methodFlags & MethodFlags.ArgumentsInMultiArray) > (MethodFlags)0)
            {
                ObjectReader objectReader = new ObjectReader(formatter);
                object       obj;
                objectReader.ReadObjectGraph(reader, hasHeaders, out obj, out headers);
                object[] array3 = (object[])obj;
                if ((byte)(returnTypeTag & ReturnTypeTag.Exception) > 0)
                {
                    ex = (Exception)array3[0];
                    if (flag)
                    {
                        callCtx = (LogicalCallContext)array3[1];
                    }
                }
                else if ((methodFlags & MethodFlags.NoArguments) > (MethodFlags)0 || (methodFlags & MethodFlags.PrimitiveArguments) > (MethodFlags)0)
                {
                    int num3 = 0;
                    if ((byte)(returnTypeTag & ReturnTypeTag.ObjectType) > 0)
                    {
                        ret = array3[num3++];
                    }
                    if (flag)
                    {
                        callCtx = (LogicalCallContext)array3[num3++];
                    }
                    if (num3 < array3.Length)
                    {
                        array2 = (object[])array3[num3];
                    }
                }
                else if ((methodFlags & MethodFlags.ArgumentsInSimpleArray) > (MethodFlags)0)
                {
                    array = array3;
                }
                else
                {
                    int num4 = 0;
                    array = (object[])array3[num4++];
                    if ((byte)(returnTypeTag & ReturnTypeTag.ObjectType) > 0)
                    {
                        ret = array3[num4++];
                    }
                    if (flag)
                    {
                        callCtx = (LogicalCallContext)array3[num4++];
                    }
                    if (num4 < array3.Length)
                    {
                        array2 = (object[])array3[num4];
                    }
                }
            }
            else
            {
                reader.ReadByte();
            }
            if (headerHandler != null)
            {
                headerHandler(headers);
            }
            if (ex != null)
            {
                return(new ReturnMessage(ex, methodCallMessage));
            }
            int           outArgsCount  = (array == null) ? 0 : array.Length;
            ReturnMessage returnMessage = new ReturnMessage(ret, array, outArgsCount, callCtx, methodCallMessage);

            if (array2 != null)
            {
                foreach (DictionaryEntry dictionaryEntry in array2)
                {
                    returnMessage.Properties[(string)dictionaryEntry.Key] = dictionaryEntry.Value;
                }
            }
            return(returnMessage);
        }