/// <summary>
        /// Stores the given value into the instance's stream; the serializer
        /// is inferred from TValue and format.
        /// </summary>
        /// <remarks>Needs to be public to be callable thru reflection in Silverlight</remarks>
        public static void AppendExtendValueTyped <TSource, TValue>(
            TSource instance, int tag, DataFormat format, TValue value)
            where TSource : class, IExtensible
        {
            Serializer <TSource> .CheckTagNotInUse(tag);

            Property <TValue, TValue> prop = PropertyFactory.CreatePassThru <TValue>(tag, ref format);

            IExtension extn = instance.GetExtensionObject(true);

            if (extn == null)
            {
                throw new InvalidOperationException("No extension object available; appended data would be lost.");
            }

            Stream stream = extn.BeginAppend();

            try
            {
                SerializationContext ctx = new SerializationContext(stream, null);
                ctx.Push(instance); // for recursion detection
                prop.Serialize(value, ctx);
                ctx.Pop(instance);
                ctx.Flush();
                extn.EndAppend(stream, true);
            }
            catch
            {
                extn.EndAppend(stream, false);
                throw;
            }
        }
        /// <summary>
        /// Reads the given value(s) from the instance's stream; the serializer
        /// is inferred from TValue and format. For singletons, each occurrence
        /// is merged [only applies for sub-objects], and the composed
        /// value if yielded once; otherwise ("repeated") each occurrence
        /// is yielded separately.
        /// </summary>
        /// <remarks>Needs to be public to be callable thru reflection in Silverlight</remarks>
        public static IEnumerable <TValue> GetExtendedValuesTyped <TSource, TValue>(
            TSource instance, int tag, DataFormat format, bool singleton, bool allowDefinedTag)
            where TSource : class, IExtensible
        {
            if (instance == null)
            {
                throw new ArgumentNullException("instance");
            }

            if (!allowDefinedTag)
            {
                Serializer <TSource> .CheckTagNotInUse(tag);
            }
            Property <TValue, TValue>         prop  = PropertyFactory.CreatePassThru <TValue>(tag, ref format);
            List <Property <TValue, TValue> > props = new List <Property <TValue, TValue> >();

            foreach (Property <TValue, TValue> altProp in prop.GetCompatibleReaders())
            {
                props.Add(altProp);
            }


            IExtension extn = instance.GetExtensionObject(false);

            if (extn == null)
            {
                yield break;
            }

            Stream stream    = extn.BeginQuery();
            TValue lastValue = default(TValue);
            bool   hasValue  = false;

            try
            {
                SerializationContext ctx = new SerializationContext(stream, null);
                uint fieldPrefix;

                while (ctx.TryReadFieldPrefix(out fieldPrefix))
                {
                    WireType a;
                    int      b;
                    Serializer.ParseFieldToken(fieldPrefix, out a, out b);

                    Property <TValue, TValue> actProp = null;
                    if (fieldPrefix == prop.FieldPrefix)
                    {
                        actProp = prop;
                    }
                    else
                    {
                        foreach (Property <TValue, TValue> x in props)
                        {
                            if (x.FieldPrefix == fieldPrefix)
                            {
                                actProp = x;
                                break;
                            }
                        }
                    }

                    if (actProp != null)
                    {
                        TValue value = actProp.DeserializeImpl(lastValue, ctx);
                        hasValue = true;
                        if (singleton)
                        {
                            // merge with later values before returning
                            lastValue = value;
                        }
                        else
                        {
                            // return immediately; no merge
                            yield return(value);
                        }
                    }
                    else
                    {
                        int      readTag;
                        WireType wireType;
                        Serializer.ParseFieldToken(fieldPrefix, out wireType, out readTag);

                        if (readTag == tag)
                        {
                            // we can't deserialize data of that type - for example,
                            // have received Fixed32 for a string, etc
                            throw new ProtoException(string.Format(
                                                         "Unexpected wire-type ({0}) found for tag {1}.",
                                                         wireType, readTag));
                        }

                        // skip all other tags
                        Serializer.SkipData(ctx, readTag, wireType);
                    }
                }
            }
            finally
            {
                extn.EndQuery(stream);
            }

            if (singleton && hasValue)
            {
                yield return(lastValue);
            }
        }