public void TestHandlesExclusive([Values(true, false)] bool detached, [Values(true, false)] bool asPortable)
        {
            var marsh = new PortableMarshaller(new PortableConfiguration
            {
                TypeConfigurations = new List<PortableTypeConfiguration>
                {
                    new PortableTypeConfiguration(typeof (HandleInner)),
                    new PortableTypeConfiguration(typeof (HandleOuterExclusive))
                }
            });

            var inner = new HandleInner
            {
                Before = "inBefore",
                After = "inAfter",
                RawBefore = "inRawBefore",
                RawAfter = "inRawAfter"
            };

            var outer = new HandleOuterExclusive
            {
                Before = "outBefore",
                After = "outAfter",
                RawBefore = "outRawBefore",
                RawAfter = "outRawAfter",
                Inner = inner,
                RawInner = inner
            };

            inner.Outer = outer;
            inner.RawOuter = outer;

            var bytes = asPortable
                ? marsh.Marshal(new PortablesImpl(marsh).ToPortable<IPortableObject>(outer))
                : marsh.Marshal(outer);

            IPortableObject outerObj;

            if (detached)
            {
                var reader = new PortableReaderImpl(marsh, new Dictionary<long, IPortableTypeDescriptor>(),
                    new PortableHeapStream(bytes), PortableMode.ForcePortable, null);

                reader.DetachNext();

                outerObj = reader.Deserialize<IPortableObject>();
            }
            else
                outerObj = marsh.Unmarshal<IPortableObject>(bytes, PortableMode.ForcePortable);

            HandleOuter newOuter = outerObj.Deserialize<HandleOuter>();

            Assert.IsFalse(newOuter == newOuter.Inner.Outer);
            Assert.IsFalse(newOuter == newOuter.Inner.RawOuter);
            Assert.IsFalse(newOuter == newOuter.RawInner.RawOuter);
            Assert.IsFalse(newOuter == newOuter.RawInner.RawOuter);

            Assert.IsFalse(newOuter.Inner == newOuter.RawInner);

            Assert.IsTrue(newOuter.Inner.Outer == newOuter.Inner.RawOuter);
            Assert.IsTrue(newOuter.RawInner.Outer == newOuter.RawInner.RawOuter);

            Assert.IsTrue(newOuter.Inner == newOuter.Inner.Outer.Inner);
            Assert.IsTrue(newOuter.Inner == newOuter.Inner.Outer.RawInner);
            Assert.IsTrue(newOuter.RawInner == newOuter.RawInner.Outer.Inner);
            Assert.IsTrue(newOuter.RawInner == newOuter.RawInner.Outer.RawInner);
        }
            /** <inheritdoc /> */
            virtual public void ReadPortable(IPortableReader reader)
            {
                Before = reader.ReadString("before");
                Inner = reader.ReadObject<HandleInner>("inner");
                After = reader.ReadString("after");

                IPortableRawReader rawReader = reader.RawReader();

                RawBefore = rawReader.ReadString();
                RawInner = rawReader.ReadObject<HandleInner>();
                RawAfter = rawReader.ReadString();
            }
        public void TestHandles()
        {
            ICollection<PortableTypeConfiguration> typeCfgs =
                new List<PortableTypeConfiguration>();

            typeCfgs.Add(new PortableTypeConfiguration(typeof(HandleInner)));
            typeCfgs.Add(new PortableTypeConfiguration(typeof(HandleOuter)));

            PortableConfiguration cfg = new PortableConfiguration();

            cfg.TypeConfigurations = typeCfgs;

            PortableMarshaller marsh = new PortableMarshaller(cfg);

            HandleOuter outer = new HandleOuter();

            outer.Before = "outBefore";
            outer.After = "outAfter";
            outer.RawBefore = "outRawBefore";
            outer.RawAfter = "outRawAfter";

            HandleInner inner = new HandleInner();

            inner.Before = "inBefore";
            inner.After = "inAfter";
            inner.RawBefore = "inRawBefore";
            inner.RawAfter = "inRawAfter";

            outer.Inner = inner;
            outer.RawInner = inner;

            inner.Outer = outer;
            inner.RawOuter = outer;

            byte[] bytes = marsh.Marshal(outer);

            IPortableObject outerObj = marsh.Unmarshal<IPortableObject>(bytes, PortableMode.ForcePortable);

            HandleOuter newOuter = outerObj.Deserialize<HandleOuter>();
            HandleInner newInner = newOuter.Inner;

            CheckHandlesConsistency(outer, inner, newOuter, newInner);

            // Get inner object by field.
            IPortableObject innerObj = outerObj.Field<IPortableObject>("inner");

            newInner = innerObj.Deserialize<HandleInner>();
            newOuter = newInner.Outer;

            CheckHandlesConsistency(outer, inner, newOuter, newInner);

            // Get outer object from inner object by handle.
            outerObj = innerObj.Field<IPortableObject>("outer");

            newOuter = outerObj.Deserialize<HandleOuter>();
            newInner = newOuter.Inner;

            CheckHandlesConsistency(outer, inner, newOuter, newInner);
        }
        private void CheckHandlesConsistency(HandleOuter outer, HandleInner inner, HandleOuter newOuter, 
            HandleInner newInner)
        {
            Assert.True(newOuter != null);
            Assert.AreEqual(outer.Before, newOuter.Before);
            Assert.True(newOuter.Inner == newInner);
            Assert.AreEqual(outer.After, newOuter.After);
            Assert.AreEqual(outer.RawBefore, newOuter.RawBefore);
            Assert.True(newOuter.RawInner == newInner);
            Assert.AreEqual(outer.RawAfter, newOuter.RawAfter);

            Assert.True(newInner != null);
            Assert.AreEqual(inner.Before, newInner.Before);
            Assert.True(newInner.Outer == newOuter);
            Assert.AreEqual(inner.After, newInner.After);
            Assert.AreEqual(inner.RawBefore, newInner.RawBefore);
            Assert.True(newInner.RawOuter == newOuter);
            Assert.AreEqual(inner.RawAfter, newInner.RawAfter);            
        }