IEnumerable <XamlNodeMember> GetNodeMembers(XamlObject xobj, IValueSerializerContext vsctx)
        {
            var member = new XamlNodeMember();

            // XData.XmlReader is not returned.
            if (ReferenceEquals(xobj.Type, XamlLanguage.XData))
            {
                yield return(member.Set(xobj, XamlLanguage.XData.GetMember("Text")));

                yield break;
            }

            // FIXME: find out why root Reference has PositionalParameters.
            if (xobj.Value != root && ReferenceEquals(xobj.Type, XamlLanguage.Reference))
            {
                yield return(member.Set(xobj, XamlLanguage.PositionalParameters));
            }
            else
            {
                var inst = xobj.Value;
                var atts = new KeyValuePair <AttachableMemberIdentifier, object> [AttachablePropertyServices.GetAttachedPropertyCount(inst)];
                AttachablePropertyServices.CopyPropertiesTo(inst, atts, 0);
                XamlObject cobj = null;
                foreach (var p in atts)
                {
                    var axt = ctx.GetXamlType(p.Key.DeclaringType);
                    if (cobj == null)
                    {
                        cobj = new XamlObject();
                    }
                    yield return(member.Set(cobj.Set(axt, p.Value), axt.GetAttachableMember(p.Key.MemberName)));
                }

                var type = xobj.Type;
                if (type.HasPositionalParameters(vsctx))
                {
                    yield return(member.Set(xobj, XamlLanguage.PositionalParameters));

                    yield break;
                }

                // Note that if the XamlType has the default constructor, we don't need "Arguments".
                IEnumerable <XamlMember> args = type.ConstructionRequiresArguments ? type.GetSortedConstructorArguments() : null;
                if (args != null && args.Any())
                {
                    yield return(member.Set(xobj, XamlLanguage.Arguments));
                }

                if (type.IsContentValue(vsctx))
                {
                    yield return(member.Set(xobj, XamlLanguage.Initialization));

                    yield break;
                }

                if (type.IsDictionary)
                {
                    yield return(member.Set(xobj, XamlLanguage.Items));

                    yield break;
                }

                var members = type.GetAllMembersAsList();
                for (int i = 0; i < members.Count; i++)
                {
                    var m = members[i];
                    // do not read constructor arguments twice (they are written inside Arguments).
                    if (args != null && args.Contains(m))
                    {
                        continue;
                    }
                    // do not return non-public members (of non-collection/xdata). Not sure why .NET filters out them though.
                    if (!m.IsReadPublic ||
                        !m.ShouldSerialize(xobj.Value))
                    {
                        continue;
                    }

                    if (!m.IsWritePublic &&
                        !m.Type.IsXData &&
                        !m.Type.IsArray &&
                        !m.Type.IsCollection &&
                        !m.Type.IsDictionary)
                    {
                        continue;
                    }

                    yield return(member.Set(xobj, m));
                }

                if (type.IsCollection)
                {
                    yield return(member.Set(xobj, XamlLanguage.Items));
                }
            }
        }