// returns StartObject, StartMember, Value, EndMember and EndObject. (NamespaceDeclaration is not included)
        public IEnumerable <XamlNodeInfo> GetNodes()
        {
            var xobj = new XamlObject(GetType(root), root);

            foreach (var node in GetNodes(null, xobj))
            {
                yield return(node);
            }
        }
Example #2
0
        string GetReferenceName(XamlObject xobj)
        {
            var xm = xobj.Type.GetAliasedProperty(XamlLanguage.Name);

            if (xm != null)
            {
                return((string)xm.Invoker.GetValue(xobj.GetRawValue()));
            }
            return("__ReferenceID" + used_reference_ids++);
        }
Example #3
0
        IEnumerable <XamlNodeInfo> GetItemsNodes(XamlMember xm, XamlObject xobj)
        {
            var obj = xobj.GetRawValue();

            if (obj == null)
            {
                yield break;
            }
            var ie = xobj.Type.Invoker.GetItems(obj);

            while (ie.MoveNext())
            {
                var iobj = ie.Current;
                // If it is dictionary, then retrieve the key, and rewrite the item as the Value part.
                object ikey = null;
                if (xobj.Type.IsDictionary)
                {
                    Type kvpType      = iobj.GetType();
                    bool isNonGeneric = kvpType == typeof(DictionaryEntry);
                    var  kp           = isNonGeneric ? null : kvpType.GetRuntimeProperty("Key");
                    var  vp           = isNonGeneric ? null : kvpType.GetRuntimeProperty("Value");
                    ikey = isNonGeneric ? ((DictionaryEntry)iobj).Key : kp.GetValue(iobj, null);
                    iobj = isNonGeneric ? ((DictionaryEntry)iobj).Value : vp.GetValue(iobj, null);
                }

                var wobj  = TypeExtensionMethods.GetExtensionWrapped(iobj);
                var xiobj = new XamlObject(GetType(wobj), wobj);
                if (ikey != null)
                {
                    // Key member is written *inside* the item object.
                    //
                    // It is messy, but Key and Value are *sorted*. In most cases Key goes first, but for example PositionalParameters comes first.
                    // To achieve this behavior, we compare XamlLanguage.Key and value's Member and returns in order. It's all nasty hack, but at least it could be achieved like this!

                    var en = GetNodes(null, xiobj).ToArray();
                    yield return(en [0]);                    // StartObject

                    var xknm   = new XamlNodeMember(xobj, XamlLanguage.Key);
                    var nodes1 = en.Skip(1).Take(en.Length - 2);
                    var nodes2 = GetKeyNodes(ikey, xobj.Type.KeyType, xknm);
                    foreach (var xn in EnumerateMixingMember(nodes1, XamlLanguage.Key, nodes2))
                    {
                        yield return(xn);
                    }
                    yield return(en [en.Length - 1]);
                }
                else
                {
                    foreach (var xn in GetNodes(null, xiobj))
                    {
                        yield return(xn);
                    }
                }
            }
        }
Example #4
0
        internal static object GetMemberValue(this XamlObject xobj, XamlMember xm)
        {
            if (xm.IsUnknown)
            {
                return(null);
            }

            if (xm.IsAttachable)
            {
                return(xobj.GetRawValue());                 // attachable property value
            }
            // FIXME: this looks like an ugly hack. Is this really true? What if there's MarkupExtension that uses another MarkupExtension type as a member type.
            var obj = xobj.Context.GetRawValue();

            if (xm == XamlLanguage.Initialization)
            {
                return(obj);
            }
            if (xm == XamlLanguage.Items)             // collection itself.
            {
                return(obj);
            }
            if (xm == XamlLanguage.Arguments)             // object itself
            {
                return(obj);
            }
            if (xm == XamlLanguage.PositionalParameters)
            {
                return(xobj.GetRawValue());                 // dummy value
            }
            TypeConverter tc  = null;
            var           cas = xm.GetCustomAttributeProvider().GetCustomAttributes(true);

            foreach (var ca in cas)
            {
                tc = TypeDescriptor.GetConverter(ca);
                if (tc != null)
                {
                    break;
                }
            }

            if (tc != null)
            {
                return(xm.UnderlyingGetter.Invoke(xobj.GetRawValue(), new object[] {}));
            }

            return(xm.Invoker.GetValue(xobj.GetRawValue()));
        }
        IEnumerable <XamlNodeInfo> GetDeferredNodes(XamlMember xm, object val)
        {
            var node   = new XamlNodeInfo();
            var reader = xm.DeferringLoader.ConverterInstance.Save(val, value_serializer_ctx);
            var xobj   = new XamlObject();

            while (reader.Read())
            {
                var nodeType = reader.NodeType;
                switch (nodeType)
                {
                case XamlNodeType.StartObject:
                case XamlNodeType.GetObject:
                    xobj.Set(reader.Type, reader.Value);
                    yield return(node.Set(nodeType, xobj));

                    break;

                case XamlNodeType.EndObject:
                    yield return(XamlNodeInfo.EndObject);

                    break;

                case XamlNodeType.StartMember:
                    yield return(node.Set(nodeType, reader.Member));

                    break;

                case XamlNodeType.EndMember:
                    yield return(XamlNodeInfo.EndMember);

                    break;

                case XamlNodeType.Value:
                    yield return(node.Set(reader.Value));

                    break;

                case XamlNodeType.NamespaceDeclaration:
                    yield return(node.Set(reader.Namespace));

                    break;

                default:
                    break;
                }
            }
        }
        IEnumerable <XamlNodeInfo> GetDeferredNodes(XamlMember xm, object val)
        {
            var reader = xm.DeferringLoader.ConverterInstance.Save(val, value_serializer_ctx);
            Stack <XamlObject> objs = new Stack <XamlObject>();

            while (reader.Read())
            {
                var nodeType = reader.NodeType;
                switch (nodeType)
                {
                case XamlNodeType.StartObject:
                case XamlNodeType.GetObject:
                    var obj = new XamlObject(reader.Type, reader.Value);
                    objs.Push(obj);
                    yield return(new XamlNodeInfo(nodeType, obj));

                    break;

                case XamlNodeType.EndObject:
                    yield return(new XamlNodeInfo(nodeType, objs.Pop()));

                    break;

                case XamlNodeType.StartMember:
                    yield return(new XamlNodeInfo(nodeType, new XamlNodeMember(objs.Peek(), reader.Member)));

                    break;

                case XamlNodeType.EndMember:
                    yield return(new XamlNodeInfo(nodeType, new XamlNodeMember(objs.Peek(), reader.Member)));

                    break;

                case XamlNodeType.Value:
                    yield return(new XamlNodeInfo(reader.Value));

                    break;

                case XamlNodeType.NamespaceDeclaration:
                    yield return(new XamlNodeInfo(reader.Namespace));

                    break;

                default:
                    break;
                }
            }
        }
Example #7
0
        internal string GetReferenceName(XamlObject xobj, object value)
        {
            var name = GetName(value);

            if (name != null)
            {
                return(name);
            }

            if (unnamed.Count == 0)
            {
                return(null);
            }

            NamedObject un = null;

            for (int i = 0; i < unnamed.Count; i++)
            {
                var r = unnamed[i];
                if (ReferenceEquals(r.Value, value))
                {
                    un = r;
                    break;
                }
            }
            if (un == null)
            {
                return(null);
            }

            // generate a name for it, only when needed.
            var xm = xobj.Type.GetAliasedProperty(XamlLanguage.Name);

            if (xm != null)
            {
                name = (string)xm.Invoker.GetValue(xobj.Value);
            }
            else
            {
                name = "__ReferenceID" + used_reference_ids++;
            }
            un.Name        = name;
            objects [name] = un;

            return(name);
        }
Example #8
0
        IEnumerable <XamlNodeInfo> GetObjectMemberNodes(XamlObject xobj)
        {
            var xce = GetNodeMembers(xobj, value_serializer_ctx).GetEnumerator();

            while (xce.MoveNext())
            {
                // XamlLanguage.Items does not show up if the content is empty.
                if (xce.Current.Member == XamlLanguage.Items)
                {
                    // FIXME: this is nasty, but this name resolution is the only side effect of this iteration model. Save-Restore procedure is required.
                    NameResolver.Save();
                    try {
                        if (!GetNodes(xce.Current.Member, xce.Current.Value).GetEnumerator().MoveNext())
                        {
                            continue;
                        }
                    } finally {
                        NameResolver.Restore();
                    }
                }

                // Other collections as well, but needs different iteration (as nodes contain GetObject and EndObject).
                if (!xce.Current.Member.IsWritePublic && xce.Current.Member.Type != null && xce.Current.Member.Type.IsCollection)
                {
                    var e = GetNodes(xce.Current.Member, xce.Current.Value).GetEnumerator();
                    // FIXME: this is nasty, but this name resolution is the only side effect of this iteration model. Save-Restore procedure is required.
                    NameResolver.Save();
                    try {
                        if (!(e.MoveNext() && e.MoveNext() && e.MoveNext()))                            // GetObject, EndObject and more
                        {
                            continue;
                        }
                    } finally {
                        NameResolver.Restore();
                    }
                }

                foreach (var cn in GetMemberNodes(xce.Current, GetNodes(xce.Current.Member, xce.Current.Value)))
                {
                    yield return(cn);
                }
            }
        }
        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));
                }
            }
        }
		string GetReferenceName (XamlObject xobj)
		{
			var xm = xobj.Type.GetAliasedProperty (XamlLanguage.Name);
			if (xm != null)
				return (string) xm.Invoker.GetValue (xobj.GetRawValue ());
			return "__ReferenceID" + used_reference_ids++;
		}
        IEnumerable <XamlNodeInfo> GetNodes(XamlMember xm, XamlObject xobj, XamlType overrideMemberType = null, bool partOfPositionalParameters = false, XamlNodeInfo node = null)
        {
            object val;

            // Value - only for non-top-level node (thus xm != null)
            if (xm != null)
            {
                // collection items: each item is exposed as a standalone object that has StartObject, EndObject and contents.
                if (ReferenceEquals(xm, XamlLanguage.Items))
                {
                    foreach (var xn in GetItemsNodes(xm, xobj))
                    {
                        yield return(xn);
                    }
                    yield break;
                }

                // Arguments: each argument is written as a standalone object
                if (ReferenceEquals(xm, XamlLanguage.Arguments))
                {
                    var xarg = new XamlObject();
                    foreach (var argm in xobj.Type.GetSortedConstructorArguments())
                    {
                        var argv = argm.Invoker.GetValue(xobj.Value);
                        xarg.Set(argm.Type, argv);
                        foreach (var cn in GetNodes(null, xarg))
                        {
                            yield return(cn);
                        }
                    }
                    yield break;
                }

                // PositionalParameters: items are from constructor arguments, written as Value node sequentially. Note that not all of them are in simple string value. Also, null values are not written as NullExtension
                if (ReferenceEquals(xm, XamlLanguage.PositionalParameters))
                {
                    var xarg = new XamlObject();
                    foreach (var argm in xobj.Type.GetSortedConstructorArguments())
                    {
                        foreach (var cn in GetNodes(argm, xarg.Set(argm.Type, xobj.GetMemberValue(argm)), null, true))
                        {
                            yield return(cn);
                        }
                    }
                    yield break;
                }
                node = node ?? new XamlNodeInfo();

                if (ReferenceEquals(xm, XamlLanguage.Initialization))
                {
                    yield return(node.Set(TypeExtensionMethods.GetStringValue(xobj.Type, xm, xobj.Value, value_serializer_ctx)));

                    yield break;
                }

                val = xobj.Value;
                if (xm.DeferringLoader != null)
                {
                    foreach (var xn in GetDeferredNodes(xm, val))
                    {
                        yield return(xn);
                    }
                    yield break;
                }

                // don't serialize default values if one is explicitly specified using the DefaultValueAttribute
                if (!partOfPositionalParameters)
                {
                    if (xm.Invoker.IsDefaultValue(val))
                    {
                        yield break;
                    }
                    if (settings.IgnoreDefaultValues && xm.DefaultValue == null)
                    {
                        if (xm.Type?.UnderlyingType?.GetTypeInfo().IsValueType == true)
                        {
                            if (Equals(val, Activator.CreateInstance(xm.Type.UnderlyingType)))
                            {
                                yield break;
                            }
                        }
                        else if (ReferenceEquals(val, null))
                        {
                            yield break;
                        }
                    }
                }

                // overrideMemberType is (so far) used for XamlLanguage.Key.
                var xtt = overrideMemberType ?? xm.Type;
                if (!xtt.IsMarkupExtension &&                 // this condition is to not serialize MarkupExtension whose type has TypeConverterAttribute (e.g. StaticExtension) as a string.
                    (xtt.IsContentValue(value_serializer_ctx) || xm.IsContentValue(value_serializer_ctx)))
                {
                    // though null value is special: it is written as a standalone object.

                    if (val == null)
                    {
                        if (!partOfPositionalParameters)
                        {
                            foreach (var xn in GetNodes(null, null_object, node: node))
                            {
                                yield return(xn);
                            }
                        }
                        else
                        {
                            yield return(node.Set(String.Empty));
                        }
                    }
                    else if (!NameResolver.IsCollectingReferences)                     // for perf, getting string value can be expensive
                    {
                        yield return(node.Set(TypeExtensionMethods.GetStringValue(xtt, xm, val, value_serializer_ctx)));
                    }
                    else if (val is Type)
                    {
                        LookupType((Type)val);
                    }
                    //new XamlTypeName(xtt.SchemaContext.GetXamlType((Type)val)).ToString(value_serializer_ctx?.GetService(typeof(INamespacePrefixLookup)) as INamespacePrefixLookup);
                    yield break;
                }

                // collection items: return GetObject and Items.
                if ((xm.Type.IsCollection || xm.Type.IsDictionary) && !xm.IsWritePublic)
                {
                    yield return(XamlNodeInfo.GetObject);

                    // Write Items member only when there are items (i.e. do not write it if it is empty).
                    var itemsValue = xobj.GetMemberObjectValue(XamlLanguage.Items);
                    var en         = GetItemsNodes(XamlLanguage.Items, itemsValue).GetEnumerator();
                    if (en.MoveNext())
                    {
                        yield return(node.Set(XamlNodeType.StartMember, XamlLanguage.Items));

                        do
                        {
                            yield return(en.Current);
                        } while (en.MoveNext());
                        yield return(XamlNodeInfo.EndMember);
                    }
                    yield return(XamlNodeInfo.EndObject);

                    yield break;
                }
                if (xm.Type.IsXData)
                {
                    var sw = new StringWriter();
                    var xw = XmlWriter.Create(sw, new XmlWriterSettings {
                        OmitXmlDeclaration = true, ConformanceLevel = ConformanceLevel.Auto
                    });
#if NETSTANDARD1_0
                    if (!ReflectionHelpers.IXmlSerializableType?.GetTypeInfo().IsAssignableFrom(val?.GetType().GetTypeInfo()) ?? false)
                    {
                        yield break;                         // do not output anything
                    }
                    ReflectionHelpers.IXmlSerializableWriteXmlMethod?.Invoke(val, new object[] { xw });
#else
                    var val3 = val as IXmlSerializable;
                    if (val3 == null)
                    {
                        yield break;                         // do not output anything
                    }
                    val3.WriteXml(xw);
#endif
                    xw.Dispose();
                    var obj = new XData {
                        Text = sw.ToString()
                    };
                    foreach (var xn in GetNodes(null, new XamlObject(XamlLanguage.XData, obj), node: node))
                    {
                        yield return(xn);
                    }
                    yield break;
                }
            }
            else
            {
                node = node ?? new XamlNodeInfo();
                val  = xobj.Value;
            }
            // Object - could become Reference
            if (val != null && !ReferenceEquals(xobj.Type, XamlLanguage.Reference))
            {
                if (xm != null && !xm.IsReadOnly && !IsPublicOrVisible(val.GetType()))
                {
                    throw new XamlObjectReaderException($"Cannot read from internal type {xobj.Type}");
                }

                if (!xobj.Type.IsContentValue(value_serializer_ctx))
                {
                    string refName = NameResolver.GetReferenceName(xobj, val);
                    if (refName != null)
                    {
                        // The target object is already retrieved, so we don't return the same object again.
                        NameResolver.SaveAsReferenced(val);                         // Record it as named object.
                        // Then return Reference object instead.

                        var xref = new XamlObject(XamlLanguage.Reference, new Reference(refName));
                        yield return(node.Set(XamlNodeType.StartObject, xref));

                        yield return(node.Set(XamlNodeType.StartMember, XamlLanguage.PositionalParameters));

                        yield return(node.Set(refName));

                        yield return(XamlNodeInfo.EndMember);

                        yield return(XamlNodeInfo.EndObject);

                        yield break;
                    }
                    else
                    {
                        // The object appeared in the xaml tree for the first time. So we store the reference with a unique name so that it could be referenced later.
                        NameResolver.SetNamedObject(val, true);                         // probably fullyInitialized is always true here.
                    }
                }

                yield return(node.Set(XamlNodeType.StartObject, xobj));

                // If this object is referenced and there is no [RuntimeNameProperty] member, then return Name property in addition.
                if (!NameResolver.IsCollectingReferences && xobj.Type.GetAliasedProperty(XamlLanguage.Name) == null)
                {
                    string name = NameResolver.GetReferencedName(xobj, val);
                    if (name != null)
                    {
                        yield return(node.Set(XamlNodeType.StartMember, XamlLanguage.Name));

                        yield return(node.Set(name));

                        yield return(XamlNodeInfo.EndMember);
                    }
                }
            }
            else
            {
                yield return(node.Set(XamlNodeType.StartObject, xobj));
            }

            // get all object member nodes
            var xce       = GetNodeMembers(xobj, value_serializer_ctx).GetEnumerator();
            var xobject   = new XamlObject();
            var startNode = new XamlNodeInfo();
            while (xce.MoveNext())
            {
                var xnm = xce.Current;

                var en = GetNodes(xnm.Member, xnm.GetValue(xobject), node: node).GetEnumerator();
                if (en.MoveNext())
                {
                    if (!xnm.Member.IsWritePublic && xnm.Member.Type != null && (xnm.Member.Type.IsCollection || xnm.Member.Type.IsDictionary))
                    {
                        // if we are a collection or dictionary without a setter, check to see if its empty first
                        var node1 = en.Current.Copy();                         // getObject
                        if (!en.MoveNext())
                        {
                            continue;
                        }
                        var node2 = en.Current.Copy();              // possibly endObject
                        if (!en.MoveNext())                         // we have one more, so it's not empty!
                        {
                            continue;
                        }

                        // if we have three nodes, then it isn't empty

                        yield return(startNode.Set(XamlNodeType.StartMember, xnm.Member));

                        yield return(node1);

                        yield return(node2);
                    }
                    else
                    {
                        yield return(startNode.Set(XamlNodeType.StartMember, xnm.Member));
                    }

                    do
                    {
                        yield return(en.Current);
                    } while (en.MoveNext());
                    yield return(XamlNodeInfo.EndMember);
                }
            }

            yield return(XamlNodeInfo.EndObject);
        }
		IEnumerable<XamlNodeMember> GetNodeMembers (XamlObject xobj, IValueSerializerContext vsctx)
		{
			// XData.XmlReader is not returned.
			if (xobj.Type == XamlLanguage.XData) {
				yield return new XamlNodeMember (xobj, XamlLanguage.XData.GetMember ("Text"));
				yield break;
			}

			// FIXME: find out why root Reference has PositionalParameters.
			if (xobj.GetRawValue () != root && xobj.Type == XamlLanguage.Reference)
				yield return new XamlNodeMember (xobj, XamlLanguage.PositionalParameters);
			else {
				var inst = xobj.GetRawValue ();
				var atts = new KeyValuePair<AttachableMemberIdentifier,object> [AttachablePropertyServices.GetAttachedPropertyCount (inst)];
				AttachablePropertyServices.CopyPropertiesTo (inst, atts, 0);
				foreach (var p in atts) {
					var axt = ctx.GetXamlType (p.Key.DeclaringType);
					yield return new XamlNodeMember (new XamlObject (axt, p.Value), axt.GetAttachableMember (p.Key.MemberName));
				}
				foreach (var xm in xobj.Type.GetAllObjectReaderMembersByType (vsctx))
					yield return new XamlNodeMember (xobj, xm);
			}
		}
Example #13
0
		internal string GetReferencedName (XamlObject xobj, object value)
		{
			if (!referenced.Contains (value))
				return null;
			return GetReferenceName (xobj, value);
		}
Example #14
0
 public XamlNodeInfo(XamlNodeType nodeType, XamlObject value)
 {
     node_type  = nodeType;
     this.value = value;
     member     = default(XamlNodeMember);
 }
Example #15
0
		public XamlNodeMember (XamlObject owner, XamlMember member)
		{
			this.owner = owner;
			this.member = member;
		}
Example #16
0
 IEnumerable <XamlNodeInfo> GetNodes(XamlMember xm, XamlObject xobj)
 {
     return(GetNodes(xm, xobj, null, false));
 }
		IEnumerable<XamlNodeInfo> GetNodes (XamlMember xm, XamlObject xobj)
		{
			return GetNodes (xm, xobj, null, false);
		}
		IEnumerable<XamlNodeInfo> GetNodes (XamlMember xm, XamlObject xobj, XamlType overrideMemberType, bool partOfPositionalParameters)
		{
			object val;
			// Value - only for non-top-level node (thus xm != null)
			if (xm != null)
			{
				// collection items: each item is exposed as a standalone object that has StartObject, EndObject and contents.
				if (xm == XamlLanguage.Items)
				{
					foreach (var xn in GetItemsNodes(xm, xobj))
						yield return xn;
					yield break;
				}

				// Arguments: each argument is written as a standalone object
				if (xm == XamlLanguage.Arguments)
				{
					foreach (var argm in xobj.Type.GetSortedConstructorArguments())
					{
						var argv = argm.Invoker.GetValue(xobj.GetRawValue());
						var xarg = new XamlObject(argm.Type, argv);
						foreach (var cn in GetNodes(null, xarg))
							yield return cn;
					}
					yield break;
				}

				// PositionalParameters: items are from constructor arguments, written as Value node sequentially. Note that not all of them are in simple string value. Also, null values are not written as NullExtension
				if (xm == XamlLanguage.PositionalParameters)
				{
					foreach (var argm in xobj.Type.GetSortedConstructorArguments())
					{
						foreach (var cn in GetNodes(argm, new XamlObject(argm.Type, xobj.GetMemberValue(argm)), null, true))
							yield return cn;
					}
					yield break;
				}

				if (xm == XamlLanguage.Initialization)
				{
					yield return new XamlNodeInfo(TypeExtensionMethods.GetStringValue(xobj.Type, xm, xobj.GetRawValue(), value_serializer_ctx));
					yield break;
				}

				val = xobj.GetRawValue();
				if (xm.DeferringLoader != null)
				{
					foreach (var xn in GetDeferredNodes(xm, val))
						yield return xn;
					yield break;
				}

				// don't serialize default values if one is explicitly specified using the DefaultValueAttribute
				if (!partOfPositionalParameters && xm.DefaultValue != null && Equals(xm.DefaultValue.Value, val))
					yield break;

				// overrideMemberType is (so far) used for XamlLanguage.Key.
				var xtt = overrideMemberType ?? xm.Type;
				if (!xtt.IsMarkupExtension && // this condition is to not serialize MarkupExtension whose type has TypeConverterAttribute (e.g. StaticExtension) as a string.
					(xtt.IsContentValue(value_serializer_ctx) || xm.IsContentValue(value_serializer_ctx))) {
					// though null value is special: it is written as a standalone object.

					if (val == null)
					{
						if (!partOfPositionalParameters)
							foreach (var xn in GetNodes(null, null_object))
								yield return xn;
						else
							yield return new XamlNodeInfo(String.Empty);
					}
					else
						yield return new XamlNodeInfo(TypeExtensionMethods.GetStringValue(xtt, xm, val, value_serializer_ctx));
					yield break;
				}

				// collection items: return GetObject and Items.
				if (xm.Type.IsCollection && !xm.IsWritePublic)
				{
					yield return new XamlNodeInfo(XamlNodeType.GetObject, xobj);
					// Write Items member only when there are items (i.e. do not write it if it is empty).
					var xnm = new XamlNodeMember(xobj, XamlLanguage.Items);
					var en = GetNodes(XamlLanguage.Items, xnm.Value).GetEnumerator();
					if (en.MoveNext())
					{
						yield return new XamlNodeInfo(XamlNodeType.StartMember, xnm);
						do
						{
							yield return en.Current;
						} while (en.MoveNext());
						yield return new XamlNodeInfo(XamlNodeType.EndMember, xnm);
					}
					yield return new XamlNodeInfo(XamlNodeType.EndObject, xobj);
					yield break;
				}
				if (xm.Type.IsXData)
				{
					var sw = new StringWriter();
					var xw = XmlWriter.Create(sw, new XmlWriterSettings() { OmitXmlDeclaration = true, ConformanceLevel = ConformanceLevel.Auto });
					var val3 = val as IXmlSerializable;
					if (val3 == null)
						yield break; // do not output anything
					val3.WriteXml(xw);
					xw.Dispose();
					var obj = new XData() { Text = sw.ToString() };
					foreach (var xn in GetNodes(null, new XamlObject(XamlLanguage.XData, obj)))
						yield return xn;
					yield break;
				}
			}
			else
				val = xobj.GetRawValue();
			// Object - could become Reference
			if (val != null && xobj.Type != XamlLanguage.Reference) {

				if (xm != null && !xm.IsReadOnly && !IsPublicOrVisible(val.GetType()))
					throw new XamlObjectReaderException($"Cannot read from internal type {xobj.Type}");

				if (!xobj.Type.IsContentValue (value_serializer_ctx)) {
					string refName = NameResolver.GetReferenceName (xobj, val);
					if (refName != null) {
						// The target object is already retrieved, so we don't return the same object again.
						NameResolver.SaveAsReferenced (val); // Record it as named object.
						// Then return Reference object instead.
						foreach (var xn in GetNodes (null, new XamlObject (XamlLanguage.Reference, new Reference (refName))))
							yield return xn;
						yield break;
					} else {
						// The object appeared in the xaml tree for the first time. So we store the reference with a unique name so that it could be referenced later.
						NameResolver.SetNamedObject (val, true); // probably fullyInitialized is always true here.
					}
				}

				yield return new XamlNodeInfo (XamlNodeType.StartObject, xobj);

				// If this object is referenced and there is no [RuntimeNameProperty] member, then return Name property in addition.
				if (!NameResolver.IsCollectingReferences && xobj.Type.GetAliasedProperty (XamlLanguage.Name) == null) {
					string name = NameResolver.GetReferencedName (xobj, val);
					if (name != null) {
						var sobj = new XamlObject (XamlLanguage.String, name);
						foreach (var cn in GetMemberNodes (new XamlNodeMember (sobj, XamlLanguage.Name), new [] { new XamlNodeInfo (name)}))
							yield return cn;
					}
				}
			}
			else
				yield return new XamlNodeInfo (XamlNodeType.StartObject, xobj);


			foreach (var xn in GetObjectMemberNodes (xobj))
				yield return xn;
				
			yield return new XamlNodeInfo (XamlNodeType.EndObject, xobj);
		}
		// returns StartObject, StartMember, Value, EndMember and EndObject. (NamespaceDeclaration is not included)
		public IEnumerable<XamlNodeInfo> GetNodes ()
		{
			var xobj = new XamlObject (GetType (root), root);
			foreach (var node in GetNodes (null, xobj))
				yield return node;
		}
		IEnumerable<XamlNodeInfo> GetItemsNodes (XamlMember xm, XamlObject xobj)
		{
			var obj = xobj.GetRawValue ();
			if (obj == null)
				yield break;
			var ie = xobj.Type.Invoker.GetItems (obj);
			while (ie.MoveNext ()) {
				var iobj = ie.Current;
				// If it is dictionary, then retrieve the key, and rewrite the item as the Value part.
				object ikey = null;
				if (xobj.Type.IsDictionary) {
					Type kvpType = iobj.GetType ();
					bool isNonGeneric = kvpType == typeof (DictionaryEntry);
					var kp = isNonGeneric ? null : kvpType.GetRuntimeProperty ("Key");
					var vp = isNonGeneric ? null : kvpType.GetRuntimeProperty ("Value");
					ikey = isNonGeneric ? ((DictionaryEntry) iobj).Key : kp.GetValue (iobj, null);
					iobj = isNonGeneric ? ((DictionaryEntry) iobj).Value : vp.GetValue (iobj, null);
				}

				var wobj = TypeExtensionMethods.GetExtensionWrapped (iobj);
				var xiobj = new XamlObject (GetType (wobj), wobj);
				if (ikey != null) {

					var en = GetNodes (null, xiobj).ToList ();
					yield return en [0]; // StartObject

					var xknm = new XamlNodeMember (xobj, XamlLanguage.Key);
					var nodes1 = en.Skip (1).Take (en.Count - 2);
					var nodes2 = GetKeyNodes (ikey, xobj.Type.KeyType, xknm);

					// group the members then sort to put the key nodes in the correct order
					var grouped = GroupMemberNodes (nodes1.Concat (nodes2))
            .OrderBy (r => r.Item1, TypeExtensionMethods.MemberComparer);
					foreach (var item in grouped) {
						foreach (var node in item.Item2)
							yield return node;
					}

					yield return en [en.Count - 1]; // EndObject
				}
				else
					foreach (var xn in GetNodes (null, xiobj))
						yield return xn;
			}
		}
		IEnumerable<XamlNodeInfo> GetObjectMemberNodes (XamlObject xobj)
		{
			var xce = GetNodeMembers (xobj, value_serializer_ctx).GetEnumerator ();
			while (xce.MoveNext ()) {
				// XamlLanguage.Items does not show up if the content is empty.
				if (xce.Current.Member == XamlLanguage.Items) {
					// FIXME: this is nasty, but this name resolution is the only side effect of this iteration model. Save-Restore procedure is required.
					NameResolver.Save ();
					try {
						if (!GetNodes (xce.Current.Member, xce.Current.Value).GetEnumerator ().MoveNext ())
							continue;
					} finally {
						NameResolver.Restore ();
					}
				}

				// Other collections as well, but needs different iteration (as nodes contain GetObject and EndObject).
				if (!xce.Current.Member.IsWritePublic && xce.Current.Member.Type != null && xce.Current.Member.Type.IsCollection) {
					var e = GetNodes (xce.Current.Member, xce.Current.Value).GetEnumerator ();
					// FIXME: this is nasty, but this name resolution is the only side effect of this iteration model. Save-Restore procedure is required.
					NameResolver.Save ();
					try {
						if (!(e.MoveNext () && e.MoveNext () && e.MoveNext ())) // GetObject, EndObject and more
							continue;
					} finally {
						NameResolver.Restore ();
					}
				}

				foreach (var cn in GetMemberNodes (xce.Current, GetNodes (xce.Current.Member, xce.Current.Value)))
					yield return cn;
			}
		}
        IEnumerable <XamlNodeInfo> GetItemsNodes(XamlMember xm, XamlObject xobj)
        {
            var obj = xobj.Value;

            if (obj == null)
            {
                yield break;
            }
            var ie    = xobj.Type.Invoker.GetItems(obj);
            var node  = new XamlNodeInfo();
            var xiobj = new XamlObject();

            while (ie.MoveNext())
            {
                var iobj = ie.Current;
                // If it is dictionary, then retrieve the key, and rewrite the item as the Value part.
                object ikey = null;
                if (xobj.Type.IsDictionary)
                {
                    Type kvpType      = iobj.GetType();
                    bool isNonGeneric = kvpType == typeof(DictionaryEntry);
                    var  kp           = isNonGeneric ? null : kvpType.GetRuntimeProperty("Key");
                    var  vp           = isNonGeneric ? null : kvpType.GetRuntimeProperty("Value");
                    ikey = isNonGeneric ? ((DictionaryEntry)iobj).Key : kp.GetValue(iobj, null);
                    iobj = isNonGeneric ? ((DictionaryEntry)iobj).Value : vp.GetValue(iobj, null);
                }

                var wobj = TypeExtensionMethods.GetExtensionWrapped(iobj);
                xiobj.Set(GetType(wobj), wobj);
                if (ikey != null)
                {
                    // TODO: do this without copying the XamlNodeInfo somehow?
                    var en = GetNodes(null, xiobj).Select(c => c.Copy()).GetEnumerator();
                    en.MoveNext();
                    yield return(en.Current);                    // StartObject

                    //var nodes1 = en.Skip (1).Take (en.Count - 2);
                    var nodes1 = new List <XamlNodeInfo>();
                    while (en.MoveNext())
                    {
                        nodes1.Add(en.Current);
                    }

                    var nodes2 = GetKeyNodes(ikey, xobj.Type.KeyType);

                    // group the members then sort to put the key nodes in the correct order
                    var grouped = GroupMemberNodes(nodes1.Take(nodes1.Count - 1).Concat(nodes2)).OrderBy(r => r.Item1, TypeExtensionMethods.MemberComparer);
                    foreach (var item in grouped)
                    {
                        foreach (var n in item.Item2)
                        {
                            yield return(n);
                        }
                    }

                    yield return(nodes1[nodes1.Count - 1]);                    // EndObject
                }
                else
                {
                    foreach (var xn in GetNodes(null, xiobj, node: node))
                    {
                        yield return(xn);
                    }
                }
            }
        }
		IEnumerable<XamlNodeInfo> GetItemsNodes (XamlMember xm, XamlObject xobj)
		{
			var obj = xobj.GetRawValue ();
			if (obj == null)
				yield break;
			var ie = xobj.Type.Invoker.GetItems (obj);
			while (ie.MoveNext ()) {
				var iobj = ie.Current;
				// If it is dictionary, then retrieve the key, and rewrite the item as the Value part.
				object ikey = null;
				if (xobj.Type.IsDictionary) {
					Type kvpType = iobj.GetType ();
					bool isNonGeneric = kvpType == typeof (DictionaryEntry);
					var kp = isNonGeneric ? null : kvpType.GetRuntimeProperty ("Key");
					var vp = isNonGeneric ? null : kvpType.GetRuntimeProperty ("Value");
					ikey = isNonGeneric ? ((DictionaryEntry) iobj).Key : kp.GetValue (iobj, null);
					iobj = isNonGeneric ? ((DictionaryEntry) iobj).Value : vp.GetValue (iobj, null);
				}

				var wobj = TypeExtensionMethods.GetExtensionWrapped (iobj);
				var xiobj = new XamlObject (GetType (wobj), wobj);
				if (ikey != null) {
					// Key member is written *inside* the item object.
					//
					// It is messy, but Key and Value are *sorted*. In most cases Key goes first, but for example PositionalParameters comes first.
					// To achieve this behavior, we compare XamlLanguage.Key and value's Member and returns in order. It's all nasty hack, but at least it could be achieved like this!

					var en = GetNodes (null, xiobj).ToArray ();
					yield return en [0]; // StartObject

					var xknm = new XamlNodeMember (xobj, XamlLanguage.Key);
					var nodes1 = en.Skip (1).Take (en.Length - 2);
					var nodes2 = GetKeyNodes (ikey, xobj.Type.KeyType, xknm);
					foreach (var xn in EnumerateMixingMember (nodes1, XamlLanguage.Key, nodes2))
						yield return xn;
					yield return en [en.Length - 1];
				}
				else
					foreach (var xn in GetNodes (null, xiobj))
						yield return xn;
			}
		}
        // returns StartObject, StartMember, Value, EndMember and EndObject. (NamespaceDeclaration is not included)
        public IEnumerable <XamlNodeInfo> GetNodes()
        {
            var xobj = new XamlObject(GetType(root), root);

            return(GetNodes(null, xobj));
        }
Example #25
0
        public XamlObject GetValue(XamlObject xobj)
        {
            var mv = Owner.GetMemberValue(Member);

            return(xobj.Set(GetType(mv), mv));
        }
Example #26
0
 public XamlNodeMember(XamlObject owner, XamlMember member)
 {
     this.owner  = owner;
     this.member = member;
 }
Example #27
0
 public XamlNodeInfo Set(XamlNodeType nodeType, XamlObject value)
 {
     NodeType = nodeType;
     Value    = value;
     return(this);
 }
Example #28
0
		internal string GetReferenceName (XamlObject xobj, object value)
		{
			var name = GetName (value);
			if (name != null)
				return name;

			var un = unnamed.FirstOrDefault (r => ReferenceEquals (r.Value, value));
			if (un == null)
				return null;
			
			// generate a name for it, only when needed.
			var xm = xobj.Type.GetAliasedProperty (XamlLanguage.Name);
			if (xm != null)
				name = (string) xm.Invoker.GetValue (xobj.GetRawValue ());
			else
				name = "__ReferenceID" + used_reference_ids++;
			un.Name = name;
			objects [name] = un;

			return name;
		}
Example #29
0
 public XamlNodeInfo(XamlNodeType nodeType, XamlObject value)
 {
     NodeType = nodeType;
     Value    = value;
 }
Example #30
0
		public XamlNodeInfo (XamlNodeType nodeType, XamlObject value)
		{
			node_type = nodeType;
			this.value = value;
			member = default (XamlNodeMember);
		}
		IEnumerable<XamlNodeInfo> GetDeferredNodes (XamlMember xm, object val)
		{
			var reader = xm.DeferringLoader.ConverterInstance.Save(val, value_serializer_ctx);
			Stack<XamlObject> objs = new Stack<XamlObject>();
			while (reader.Read())
			{
				var nodeType = reader.NodeType;
				switch (nodeType)
				{
					case XamlNodeType.StartObject:
					case XamlNodeType.GetObject:
						var obj = new XamlObject(reader.Type, reader.Value);
						objs.Push(obj);
						yield return new XamlNodeInfo(nodeType, obj);
						break;
					case XamlNodeType.EndObject:
						yield return new XamlNodeInfo(nodeType, objs.Pop());
						break;
					case XamlNodeType.StartMember:
						yield return new XamlNodeInfo(nodeType, new XamlNodeMember(objs.Peek(), reader.Member));
						break;
					case XamlNodeType.EndMember:
						yield return new XamlNodeInfo(nodeType, new XamlNodeMember(objs.Peek(), reader.Member));
						break;
					case XamlNodeType.Value:
						yield return new XamlNodeInfo(reader.Value);
						break;
					case XamlNodeType.NamespaceDeclaration:
						yield return new XamlNodeInfo(reader.Namespace);
						break;
					default:
						break;
				}
			}
		}
Example #32
0
        IEnumerable <XamlNodeInfo> GetNodes(XamlMember xm, XamlObject xobj, XamlType overrideMemberType, bool partOfPositionalParameters)
        {
            // collection items: each item is exposed as a standalone object that has StartObject, EndObject and contents.
            if (xm == XamlLanguage.Items)
            {
                foreach (var xn in GetItemsNodes(xm, xobj))
                {
                    yield return(xn);
                }
                yield break;
            }

            // Arguments: each argument is written as a standalone object
            if (xm == XamlLanguage.Arguments)
            {
                foreach (var argm in xobj.Type.GetSortedConstructorArguments())
                {
                    var argv = argm.Invoker.GetValue(xobj.GetRawValue());
                    var xarg = new XamlObject(argm.Type, argv);
                    foreach (var cn in GetNodes(null, xarg))
                    {
                        yield return(cn);
                    }
                }
                yield break;
            }

            // PositionalParameters: items are from constructor arguments, written as Value node sequentially. Note that not all of them are in simple string value. Also, null values are not written as NullExtension
            if (xm == XamlLanguage.PositionalParameters)
            {
                foreach (var argm in xobj.Type.GetSortedConstructorArguments())
                {
                    foreach (var cn in GetNodes(argm, new XamlObject(argm.Type, xobj.GetMemberValue(argm)), null, true))
                    {
                        yield return(cn);
                    }
                }
                yield break;
            }

            if (xm == XamlLanguage.Initialization)
            {
                yield return(new XamlNodeInfo(TypeExtensionMethods.GetStringValue(xobj.Type, xm, xobj.GetRawValue(), value_serializer_ctx)));

                yield break;
            }

            // Value - only for non-top-level node (thus xm != null)
            if (xm != null)
            {
                // overrideMemberType is (so far) used for XamlLanguage.Key.
                var xtt = overrideMemberType ?? xm.Type;
                if (!xtt.IsMarkupExtension &&                 // this condition is to not serialize MarkupExtension whose type has TypeConverterAttribute (e.g. StaticExtension) as a string.
                    (xtt.IsContentValue(value_serializer_ctx) || xm.IsContentValue(value_serializer_ctx)))
                {
                    // though null value is special: it is written as a standalone object.
                    var val = xobj.GetRawValue();
                    if (val == null)
                    {
                        if (!partOfPositionalParameters)
                        {
                            foreach (var xn in GetNodes(null, null_object))
                            {
                                yield return(xn);
                            }
                        }
                        else
                        {
                            yield return(new XamlNodeInfo(String.Empty));
                        }
                    }
                    else
                    {
                        yield return(new XamlNodeInfo(TypeExtensionMethods.GetStringValue(xtt, xm, val, value_serializer_ctx)));
                    }
                    yield break;
                }
            }

            // collection items: return GetObject and Items.
            if (xm != null && xm.Type.IsCollection && !xm.IsWritePublic)
            {
                yield return(new XamlNodeInfo(XamlNodeType.GetObject, xobj));

                // Write Items member only when there are items (i.e. do not write it if it is empty).
                var xnm = new XamlNodeMember(xobj, XamlLanguage.Items);
                var en  = GetNodes(XamlLanguage.Items, xnm.Value).GetEnumerator();
                if (en.MoveNext())
                {
                    yield return(new XamlNodeInfo(XamlNodeType.StartMember, xnm));

                    do
                    {
                        yield return(en.Current);
                    } while (en.MoveNext());
                    yield return(new XamlNodeInfo(XamlNodeType.EndMember, xnm));
                }
                yield return(new XamlNodeInfo(XamlNodeType.EndObject, xobj));
            }
            else if (xm != null && xm.Type.IsXData)
            {
                var sw = new StringWriter();
                var xw = XmlWriter.Create(sw, new XmlWriterSettings()
                {
                    OmitXmlDeclaration = true, ConformanceLevel = ConformanceLevel.Auto
                });
                var val = xobj.GetRawValue() as IXmlSerializable;
                if (val == null)
                {
                    yield break;                     // do not output anything
                }
                val.WriteXml(xw);
                xw.Dispose();
                var obj = new XData()
                {
                    Text = sw.ToString()
                };
                foreach (var xn in GetNodes(null, new XamlObject(XamlLanguage.XData, obj)))
                {
                    yield return(xn);
                }
            }
            else
            {
                // Object - could become Reference
                var val = xobj.GetRawValue();
                if (!xobj.Type.IsContentValue(value_serializer_ctx) && val != null)
                {
                    string refName = NameResolver.GetName(val);
                    if (refName != null)
                    {
                        // The target object is already retrieved, so we don't return the same object again.
                        NameResolver.SaveAsReferenced(val);                          // Record it as named object.
                        // Then return Reference object instead.
                        foreach (var xn in GetNodes(null, new XamlObject(XamlLanguage.Reference, new Reference(refName))))
                        {
                            yield return(xn);
                        }
                        yield break;
                    }
                    else
                    {
                        // The object appeared in the xaml tree for the first time. So we store the reference with a unique name so that it could be referenced later.
                        refName = GetReferenceName(xobj);
                        if (NameResolver.IsCollectingReferences && NameResolver.Contains(refName))
                        {
                            throw new InvalidOperationException(String.Format("There is already an object of type {0} named as '{1}'. Object names must be unique.", val.GetType(), refName));
                        }
                        NameResolver.SetNamedObject(refName, val, true);                          // probably fullyInitialized is always true here.
                    }
                }
                yield return(new XamlNodeInfo(XamlNodeType.StartObject, xobj));

                // If this object is referenced and there is no [RuntimeNameProperty] member, then return Name property in addition.
                if (val != null && xobj.Type.GetAliasedProperty(XamlLanguage.Name) == null)
                {
                    string name = NameResolver.GetReferencedName(val);
                    if (name != null)
                    {
                        var sobj = new XamlObject(XamlLanguage.String, name);
                        foreach (var cn in GetMemberNodes(new XamlNodeMember(sobj, XamlLanguage.Name), new XamlNodeInfo [] { new XamlNodeInfo(name) }))
                        {
                            yield return(cn);
                        }
                    }
                }
                foreach (var xn in GetObjectMemberNodes(xobj))
                {
                    yield return(xn);
                }
                yield return(new XamlNodeInfo(XamlNodeType.EndObject, xobj));
            }
        }
Example #33
0
 public XamlNodeMember Set(XamlObject owner, XamlMember member)
 {
     Owner  = owner;
     Member = member;
     return(this);
 }