コード例 #1
0
        /// <summary>Reads a remote exception from the stream.</summary>
        /// <returns>The remote exception.</returns>
        public RemoteException ReadException()
        {
            Push(InstanceType.Exception);
            Debug.Assert(_current != null);

            RemoteException?remoteEx = null;

            do
            {
                // Read the slice header; an exception's type ID cannot be null.
                string typeId = ReadSliceHeaderIntoCurrent() !;
                ReadIndirectionTableIntoCurrent(); // we read the indirection table immediately

                if (Communicator.FindRemoteExceptionFactory(typeId) is IRemoteExceptionFactory factory)
                {
                    remoteEx = factory.Read(this);
                }
                else if (SkipSlice()) // Slice off what we don't understand.
                {
                    remoteEx = new RemoteException(GetSlicedData() !.Value);
                }
            }while (remoteEx == null);

            Pop(null);
            return(remoteEx);
        }
コード例 #2
0
        /// <summary>Reads a remote exception from the stream.</summary>
        /// <returns>The remote exception.</returns>
        public RemoteException ReadException()
        {
            if (!_inEncapsulation)
            {
                throw new InvalidOperationException("cannot read an exception outside an encapsulation");
            }
            if (Communicator == null)
            {
                throw new InvalidOperationException(
                          "cannot read an exception from an InputStream with a null communicator");
            }

            Debug.Assert(_current.InstanceType == InstanceType.None);
            _current.InstanceType = InstanceType.Exception;

            RemoteException?      remoteEx     = null;
            string?               errorMessage = null;
            RemoteExceptionOrigin?origin       = null;

            // The unmarshaling of remote exceptions is similar with the 1.1 and 2.0 encodings, in particular we can
            // read the indirection table (if there is one) immediately after reading each slice header because the
            // indirection table cannot reference the exception itself.
            // With the 1.1 encoding, each slice contains its type ID (as a string), while with the 2.0 encoding the
            // first slice contains all the type IDs.

            if (OldEncoding)
            {
                do
                {
                    // The type ID is always read for an exception and cannot be null.
                    (string?typeId, _) = ReadSliceHeaderIntoCurrent11();
                    Debug.Assert(typeId != null);

                    ReadIndirectionTableIntoCurrent(); // we read the indirection table immediately.

                    if (Communicator.FindRemoteExceptionFactory(typeId) is
                        Func <string?, RemoteExceptionOrigin?, RemoteException> factory)
                    {
                        // The 1.1 encoding does not carry the error message or origin so they are always null.
                        remoteEx = factory(errorMessage, origin);
                    }
                    else if (SkipSlice(typeId)) // Slice off what we don't understand.
                    {
                        break;
                    }
                }while (remoteEx == null);
            }
            else
            {
                // The type IDs are always read and cannot be null or empty.
                string[]? allTypeIds;
                (allTypeIds, errorMessage, origin) = ReadFirstSliceHeaderIntoCurrent20();
                Debug.Assert(allTypeIds != null && allTypeIds.Length > 0 && errorMessage != null);
                bool firstSlice = true;

                foreach (string typeId in allTypeIds)
                {
                    if (firstSlice)
                    {
                        firstSlice = false;
                    }
                    else
                    {
                        ReadNextSliceHeaderIntoCurrent();
                    }
                    ReadIndirectionTableIntoCurrent(); // we read the indirection table immediately.

                    Func <string?, RemoteExceptionOrigin?, RemoteException>?factory =
                        Communicator.FindRemoteExceptionFactory(typeId);
                    if (factory != null)
                    {
                        remoteEx = factory(errorMessage, origin);
                        break; // foreach
                    }
                    else if (SkipSlice(typeId))
                    {
                        // It should be the last element of allTypeIds; if it's not, we'll fail when reading the slices.
                        break;
                    }
                    // else, loop.
                }
            }

            remoteEx ??= new RemoteException(errorMessage);
            remoteEx.Read(this);

            _current = default;
            return(remoteEx);
        }