Пример #1
0
 /// <summary>
 /// Finds a property with the specified XML element information.
 /// </summary>
 /// <param name="xml">The XML information to find.</param>
 /// <returns>
 /// A PropertyInfo for the first property found matching the specified
 /// information or null if no matches were found.
 /// </returns>
 public PropertyInfo FindElement(XmlComponent xml)
 {
     return(this.elements
            .Where(e => e.Item1.Equals(xml))
            .Select(e => e.Item2)
            .FirstOrDefault());
 }
Пример #2
0
        /// <summary>
        /// Registers the specified type with the specified XML name and
        /// namespace URI.
        /// </summary>
        /// <typeparam name="T">
        /// The type of the class to be registered, deriving from
        /// <see cref="Element"/>.
        /// </typeparam>
        /// <param name="xml">The XML information of the element.</param>
        /// <exception cref="ArgumentNullException">xml is null.</exception>
        /// <exception cref="ArgumentException">
        /// The type has already been registered or another type with the
        /// same XML name and namespace URI has been already registered.
        /// </exception>
        public static void Register <T>(XmlComponent xml)
            where T : Element
        {
            Check.IsNotNull(xml, nameof(xml));

            RegisterType(xml.Clone(), typeof(T)); // Don't store what the user passed us
        }
Пример #3
0
        private IEnumerable <ElementInfo> ExtractPropertyElements(TypeInfo typeInfo)
        {
            bool IsSerializableProperty(PropertyInfo property)
            {
                return(property.CanRead &&
                       !property.GetMethod.IsStatic &&
                       (property.CanWrite || IsEnumerable(property)));
            }

            foreach (PropertyInfo property in typeInfo.DeclaredProperties.Where(IsSerializableProperty))
            {
                KmlAttributeAttribute attribute = GetAttribute <KmlAttributeAttribute>(property);
                if (attribute != null)
                {
                    var component = new XmlComponent(null, attribute.AttributeName, null);

                    // Check if a property has already been registered with the info.
                    // Ignore later properties - i.e. don't throw an exception.
                    if (!this.attributes.ContainsKey(component))
                    {
                        this.attributes.Add(component, new ElementInfo(property, attribute));
                    }
                }
                else
                {
                    KmlElementAttribute kmlElement = GetElement(property);
                    if (kmlElement != null)
                    {
                        yield return(new ElementInfo(property, kmlElement));
                    }
                }
            }
        }
Пример #4
0
        private static bool WriteStartTag(XmlWriter writer, XmlNamespaceManager manager, Element element, out string ns)
        {
            ns = null;

            // Custom elements take priority over component
            if (element is ICustomElement customElement)
            {
                customElement.CreateStartElement(writer);
                if (!customElement.ProcessChildren)
                {
                    return(false); // Don't need to do any more work.
                }
            }
            else
            {
                XmlComponent component = KmlFactory.FindType(element.GetType());
                if (component == null)
                {
                    // We can't handle it so ignore it
                    System.Diagnostics.Debug.WriteLine("Unknown Element type - please register first." + element.GetType());
                    return(false);
                }

                ns = component.NamespaceUri;
                string prefix = FindPrefix(manager, ns);
                writer.WriteStartElement(prefix, component.Name, component.NamespaceUri);
            }

            return(true);
        }
Пример #5
0
        /// <summary>
        /// Finds a property with the specified XML element information.
        /// </summary>
        /// <param name="xml">The XML information to find.</param>
        /// <returns>
        /// A PropertyInfo for the first property found matching the specified
        /// information or null if no matches were found.
        /// </returns>
        public PropertyInfo FindElement(XmlComponent xml)
        {
            var query = from element in _elements
                        where element.Item1.Equals(xml)
                        select element.Item2;

            return(query.FirstOrDefault());
        }
Пример #6
0
        /// <summary>
        /// Finds a property with the specified XML attribute information.
        /// </summary>
        /// <param name="xml">The XML information to find.</param>
        /// <returns>
        /// A PropertyInfo for the first property found matching the specified
        /// information or null if no matches were found.
        /// </returns>
        public PropertyInfo FindAttribute(XmlComponent xml)
        {
            if (this.attributes.TryGetValue(xml, out Tuple <PropertyInfo, KmlAttributeAttribute> property))
            {
                return(property.Item1);
            }

            return(null);
        }
Пример #7
0
        /// <summary>
        /// Creates a derived class of <see cref="Element"/> based on the XML
        /// information.
        /// </summary>
        /// <param name="xml">The XML information of the element.</param>
        /// <returns>
        /// A derived class of <c>Element</c> if the specified information was
        /// found; otherwise, null.
        /// </returns>
        /// <exception cref="System.MemberAccessException">
        /// Cannot create an instance of an abstract class, or this member was
        /// invoked with a late-binding mechanism.
        /// </exception>
        /// <exception cref="System.Reflection.TargetInvocationException">
        /// The constructor being called throws an exception.
        /// </exception>
        public static Element CreateElement(XmlComponent xml)
        {
            if (Types.TryGetValue(xml, out Func <Element> constructor))
            {
                return(constructor());
            }

            return(null);
        }
Пример #8
0
        /// <summary>
        /// Creates a derived class of <see cref="Element"/> based on the XML
        /// information.
        /// </summary>
        /// <param name="xml">The XML information of the element.</param>
        /// <returns>
        /// A derived class of <c>Element</c> if the specified information was
        /// found; otherwise, null.
        /// </returns>
        /// <exception cref="System.MemberAccessException">
        /// Cannot create an instance of an abstract class, or this member was
        /// invoked with a late-binding mechanism.
        /// </exception>
        /// <exception cref="System.Reflection.TargetInvocationException">
        /// The constructor being called throws an exception.
        /// </exception>
        public static Element CreateElement(XmlComponent xml)
        {
            if (Types.TryGetValue(xml, out Type type))
            {
                return((Element)Activator.CreateInstance(type));
            }

            return(null);
        }
Пример #9
0
        /// <summary>
        /// Registers the specified type with the specified XML name and
        /// namespace URI.
        /// </summary>
        /// <typeparam name="T">
        /// The type of the class to be registered, deriving from
        /// <see cref="Element"/>.
        /// </typeparam>
        /// <param name="xml">The XML information of the element.</param>
        /// <exception cref="ArgumentNullException">xml is null.</exception>
        /// <exception cref="ArgumentException">
        /// The type has already been registered or another type with the
        /// same XML name and namespace URI has been already registered.
        /// </exception>
        public static void Register <T>(XmlComponent xml) where T : Element
        {
            if (xml == null)
            {
                throw new ArgumentNullException("xml");
            }

            RegisterType(xml.Clone(), typeof(T)); // Don't store what the user passed us
        }
Пример #10
0
        private static void RegisterElement(Type type)
        {
            KmlElementAttribute element = TypeBrowser.GetElement(type.GetTypeInfo());

            if (element != null)
            {
                var xml = new XmlComponent(null, element.ElementName, element.Namespace);
                RegisterType(xml, type);
            }
        }
Пример #11
0
        private static void SerializeElement(XmlWriter writer, Element element)
        {
            // Write start tag
            XmlComponent component = KmlFactory.FindType(element.GetType());

            // Custom elements take priority over component
            ICustomElement customElement = element as ICustomElement;

            if (customElement != null)
            {
                customElement.CreateStartElement(writer);
                if (!customElement.ProcessChildren)
                {
                    return; // Don't need to to any more work.
                }
            }
            else if (component != null)
            {
                writer.WriteStartElement(component.Name, component.NamespaceUri);
            }
            else
            {
                // We can't handle it so ignore it
                System.Diagnostics.Debug.WriteLine("Unknown Element type - please register first." + element.GetType());
                return; // Skip
            }

            // Write the attributes - unknown, serialized then namespaces.
            foreach (var att in element.Attributes)
            {
                writer.WriteAttributeString(att.Prefix, att.Name, att.NamespaceUri, att.Value);
            }

            WriteAttributes(writer, element);

            foreach (var ns in element.Namespaces.GetNamespacesInScope(XmlNamespaceScope.ExcludeXml))
            {
                writer.WriteAttributeString("xmlns", ns.Key, string.Empty, ns.Value);
            }

            // Now the text part
            WriteData(writer, element.InnerText);

            // Now write the elements - serialized, children then unknown children.
            WriteElements(writer, element);
            SerializeElements(writer, element.OrderedChildren);
            SerializeElements(writer, element.Orphans);

            // Finished...
            writer.WriteEndElement();
        }
Пример #12
0
        // Private helper function to ensure both dicionaries are updated.
        private static void RegisterType(XmlComponent xml, Type type)
        {
            if (_names.ContainsKey(type))
            {
                throw new ArgumentException("Class type has already been registered.");
            }

            if (_types.ContainsKey(xml))
            {
                throw new ArgumentException("Another type has been registered with the specified XML qualified name.");
            }

            _names.Add(type, xml);
            _types.Add(xml, type);
        }
Пример #13
0
 private static void RegisterAssembly(Assembly assembly)
 {
     foreach (var type in assembly.GetExportedTypes())
     {
         if (type.IsSubclassOf(typeof(Element)))
         {
             KmlElementAttribute element = TypeBrowser.GetElement(type);
             if (element != null)
             {
                 var xml = new XmlComponent(null, element.ElementName, element.Namespace);
                 RegisterType(xml, type);
             }
         }
     }
 }
Пример #14
0
        /// <summary>
        /// Finds a property with the specified XML element information.
        /// </summary>
        /// <param name="xml">The XML information to find.</param>
        /// <returns>
        /// A PropertyInfo for the first property found matching the specified
        /// information or null if no matches were found.
        /// </returns>
        public PropertyInfo FindElement(XmlComponent xml)
        {
            var query = from element in this.elements
                        where element.Item1.Equals(xml)
                        select element.Item2;

            var propInfo = query.FirstOrDefault();

            // try looking without the namespace
            if (propInfo == null)
            {
                propInfo = this.elements.Where(e => e.Item1.Name == xml.Name).Select(e => e.Item2).FirstOrDefault();
            }
            return(propInfo);
        }
Пример #15
0
        /// <summary>
        /// Creates a derived class of <see cref="Element"/> based on the XML
        /// information.
        /// </summary>
        /// <param name="xml">The XML information of the element.</param>
        /// <returns>
        /// A derived class of <c>Element</c> if the specified information was
        /// found; otherwise, null.
        /// </returns>
        /// <exception cref="System.MemberAccessException">
        /// Cannot create an instance of an abstract class, or this member was
        /// invoked with a late-binding mechanism.
        /// </exception>
        /// <exception cref="System.Reflection.TargetInvocationException">
        /// The constructor being called throws an exception.
        /// </exception>
        public static Element CreateElement(XmlComponent xml)
        {
            Type type;

            if (Types.TryGetValue(xml, out type))
            {
                return((Element)Activator.CreateInstance(type));
            }
            //check and see if the namespace is wrong but is in the 2.2
            if (Kml22ElementTypes.TryGetValue(xml.Name, out type))
            {
                return((Element)Activator.CreateInstance(type));
            }

            return(null);
        }
Пример #16
0
        private void ExtractAttributes(Type type)
        {
            if (type == null || type == typeof(object))
            {
                return; // We've reached the top, now we have to stop
            }

            // Look at the base type first as the KML schema specifies <sequence>
            // This will also find private fields in the base classes, which can't
            // be seen through a derived class.
            this.ExtractAttributes(type.BaseType);

            // Store the found elements here so we can add them in order later
            var elements = new List <Tuple <XmlComponent, PropertyInfo, KmlElementAttribute> >();
            const BindingFlags PropertyFlags = BindingFlags.DeclaredOnly |
                                               BindingFlags.Instance |
                                               BindingFlags.NonPublic |
                                               BindingFlags.Public;

            foreach (var property in type.GetProperties(PropertyFlags))
            {
                var attribute = GetAttribute(property);
                if (attribute != null)
                {
                    XmlComponent component = new XmlComponent(null, attribute.AttributeName, null);

                    // Check if a property has already been registered with the info.
                    // Ignore later properties - i.e. don't throw an exception.
                    if (!_attributes.ContainsKey(component))
                    {
                        _attributes.Add(component, Tuple.Create(property, attribute));
                    }
                }
                else
                {
                    var element = GetElement(property);
                    if (element != null)
                    {
                        XmlComponent component = new XmlComponent(null, element.ElementName, element.Namespace);
                        elements.Add(Tuple.Create(component, property, element));
                    }
                }
            }

            // Now add the elements in order
            _elements.AddRange(elements.OrderBy(e => e.Item3.Order));
        }
Пример #17
0
        private void ExtractAttributes(Type type)
        {
            if (type == null || type == typeof(object))
            {
                return; // We've reached the top, now we have to stop
            }

            // Look at the base type first as the KML schema specifies <sequence>
            // This will also find private fields in the base classes, which can't
            // be seen through a derived class.
            TypeInfo typeInfo = type.GetTypeInfo();

            this.ExtractAttributes(typeInfo.BaseType);

            // Store the found elements here so we can add them in order later
            var elements = new List <Tuple <XmlComponent, PropertyInfo, KmlElementAttribute> >();

            foreach (PropertyInfo property in typeInfo.DeclaredProperties.Where(p => !p.GetMethod.IsStatic))
            {
                KmlAttributeAttribute attribute = GetAttribute(property);
                if (attribute != null)
                {
                    var component = new XmlComponent(null, attribute.AttributeName, null);

                    // Check if a property has already been registered with the info.
                    // Ignore later properties - i.e. don't throw an exception.
                    if (!this.attributes.ContainsKey(component))
                    {
                        this.attributes.Add(component, Tuple.Create(property, attribute));
                    }
                }
                else
                {
                    KmlElementAttribute element = GetElement(property);
                    if (element != null)
                    {
                        var component = new XmlComponent(null, element.ElementName, element.Namespace);
                        elements.Add(Tuple.Create(component, property, element));
                    }
                }
            }

            // Now add the elements in order
            this.elements.AddRange(elements.OrderBy((Tuple <XmlComponent, PropertyInfo, KmlElementAttribute> e) => e.Item3.Order));
        }
Пример #18
0
        /// <summary>
        /// Creates a derived class of <see cref="Element"/> based on the XML
        /// information.
        /// </summary>
        /// <param name="xml">The XML information of the element.</param>
        /// <returns>
        /// A derived class of <c>Element</c> if the specified information was
        /// found; otherwise, null.
        /// </returns>
        /// <exception cref="System.MemberAccessException">
        /// Cannot create an instance of an abstract class, or this member was
        /// invoked with a late-binding mechanism.
        /// </exception>
        /// <exception cref="System.Reflection.TargetInvocationException">
        /// The constructor being called throws an exception.
        /// </exception>
        public static Element CreateElement(XmlComponent xml)
        {
            if (Types.TryGetValue(xml, out Func <Element> constructor))
            {
                return(constructor());
            }

            if (string.IsNullOrEmpty(xml?.Namespace))
            {
                var comp = new XmlComponent(string.Empty, xml.Name, KmlNamespaces.Kml22Namespace);
                if (Types.TryGetValue(xml, out Func <Element> cons))
                {
                    return(cons());
                }
            }

            return(null);
        }
Пример #19
0
 /// <summary>
 /// Finds a property with the specified XML element information.
 /// </summary>
 /// <param name="xml">The XML information to find.</param>
 /// <returns>
 /// A PropertyInfo for the first property found matching the specified
 /// information or null if no matches were found.
 /// </returns>
 public ElementInfo FindElement(XmlComponent xml)
 {
     this.elements.TryGetValue(xml, out ElementInfo info);
     return(info);
 }
Пример #20
0
 /// <summary>
 /// Finds a property with the specified XML attribute information.
 /// </summary>
 /// <param name="xml">The XML information to find.</param>
 /// <returns>
 /// The information for the first property found matching the specified
 /// information or null if no matches were found.
 /// </returns>
 public ElementInfo FindAttribute(XmlComponent xml)
 {
     this.attributes.TryGetValue(xml, out ElementInfo info);
     return(info);
 }