private static void SerialiseInnerResource(XmlWriter writer, LinkedResource resource)
        {
            writer.WriteStartElement("resource");

            SetSelfLink(resource);
            SerialiseLinks(writer, resource.Links);
            SerialiseProperties(writer, resource);

            writer.WriteEndElement();
        }
        private static void SerialiseProperties(XmlWriter writer, LinkedResource resource)
        {
            var properties = resource.GetType()
                                     .GetProperties(BindingFlags.Public | BindingFlags.Instance)
                                     .Where(p => !p.Name.Equals("rel", StringComparison.InvariantCultureIgnoreCase) &&
                                                 !p.Name.Equals("href", StringComparison.InvariantCultureIgnoreCase));

            foreach (var property in properties)
            {
                var propertyValue = property.GetValue(resource);
                if (property.PropertyType.IsPrimitive || property.PropertyType == typeof(string))
                {
                    writer.WriteElementString(property.Name.ToCamelCase(), propertyValue.ToString());
                }
                else
                {
                    var value = propertyValue as LinkedResource;
                    if (value != null)
                    {
                        SerialiseInnerResource(writer, value);
                    }
                }
            }
        }
        private static void SerialiseResources(XmlWriter writer, Type type, LinkedResource resource)
        {
            if (FormatterHelper.IsLinkedResourceCollectionType(type))
            {
                writer.WriteStartElement("resources");

                foreach (LinkedResource innerResource in (IEnumerable)resource)
                {
                    SerialiseInnerResource(writer, innerResource);
                }

                writer.WriteEndElement();
            }
            else
            {
                SerialiseProperties(writer, resource);
            }
        }
        private static void SetSelfLink(LinkedResource resource)
        {
            if (string.IsNullOrWhiteSpace(resource.Href))
            {
                return;
            }

            var links = resource.Links;
            if (links.Any(p => p.Rel.Equals("self", StringComparison.InvariantCultureIgnoreCase)))
            {
                return;
            }

            resource.Links.Insert(0, new Link() { Rel = "self", Href = resource.Href });
        }
        private static void SetSelfLink(LinkedResource resource, IList<KeyValuePair<string, Link>> links)
        {
            if (string.IsNullOrWhiteSpace(resource.Href))
            {
                return;
            }

            if (links.Any(p => p.Key.Equals("self", StringComparison.InvariantCultureIgnoreCase)))
            {
                return;
            }

            links.Insert(0, new KeyValuePair<string, Link>("self", new Link() { Rel = "self", Href = resource.Href }));
        }
        private static void AddLinksToResource(LinkedResource resource, JToken jo)
        {
            var links = resource.Links.Select(p => new KeyValuePair<string, Link>(p.Rel, p)).ToList();
            SetSelfLink(resource, links);

            var jlo = SerialiseLinks(links);
            jo["_links"] = jlo;
        }
        private static void AddLinksToEmbeddedResource(Type type, object value, JToken jo)
        {
            var embedded = jo["_embedded"] as JArray;
            if (embedded == null)
            {
                return;
            }

            if (!FormatterHelper.IsLinkedResourceCollectionType(type))
            {
                return;
            }

            var resources = new LinkedResource[((ICollection)value).Count];
            ((ICollection)value).CopyTo(resources, 0);

            for (var i = 0; i < resources.Length; i++)
            {
                var resource = resources[i];
                AddLinksToResource(resource, embedded[i]);
            }
        }