diff options
Diffstat (limited to 'mcs/class/PresentationFramework/System.Windows.Serialization/Parser.cs')
-rw-r--r-- | mcs/class/PresentationFramework/System.Windows.Serialization/Parser.cs | 275 |
1 files changed, 275 insertions, 0 deletions
diff --git a/mcs/class/PresentationFramework/System.Windows.Serialization/Parser.cs b/mcs/class/PresentationFramework/System.Windows.Serialization/Parser.cs new file mode 100644 index 00000000000..3b50d5c8dd2 --- /dev/null +++ b/mcs/class/PresentationFramework/System.Windows.Serialization/Parser.cs @@ -0,0 +1,275 @@ +// +// CodeWriter.cs +// +// Author: +// Iain McCoy (iain@mccoy.id.au) +// +// (C) 2005 Iain McCoy +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Reflection; +using System.IO; +using System.Collections; +using System.CodeDom; +using System.CodeDom.Compiler; +using System.ComponentModel; +using System.Diagnostics; +using System.Windows; +using Mono.Windows.Serialization; +using System.Xml; + +namespace System.Windows.Serialization { + public class Parser { + private object instance; + ArrayList objects = new ArrayList(); + + public static object LoadXml(Stream s) + { + return LoadXml(new XmlTextReader(s)); + } + // TODO: this should take a XmlReader in order to be same as MSFT + public static object LoadXml(XmlTextReader reader) + { + Parser r = new Parser(reader); + return r.instance; + } + private Parser(XmlTextReader reader) + { + XamlParser p = new XamlParser(reader); + XamlNode n; + while (true) { + n = p.GetNextNode(); + if (n == null) + break; + Debug.WriteLine("ObjectWriter: INCOMING " + n.GetType()); + if (n is XamlDocumentStartNode) { + Debug.WriteLine("ObjectWriter: document begins"); + // do nothing + } else if (n is XamlElementStartNode && n.Depth == 0) { + Debug.WriteLine("ObjectWriter: element begins as top-level"); + CreateTopLevel(((XamlElementStartNode)n).ElementType, ((XamlElementStartNode)n).name); + } else if (n is XamlElementStartNode && peek() is PropertyInfo) { + Debug.WriteLine("ObjectWriter: element begins as property value"); + CreatePropertyObject(((XamlElementStartNode)n).ElementType, ((XamlElementStartNode)n).name); + } else if (n is XamlElementStartNode) { + Debug.WriteLine("ObjectWriter: element begins"); + CreateObject(((XamlElementStartNode)n).ElementType, ((XamlElementStartNode)n).name); + } else if (n is XamlPropertyNode && ((XamlPropertyNode)n).PropInfo != null) { + Debug.WriteLine("ObjectWriter: normal property begins"); + CreateProperty(((XamlPropertyNode)n).PropInfo); + } else if (n is XamlPropertyNode && ((XamlPropertyNode)n).DP != null) { + Debug.WriteLine("ObjectWriter: dependency property begins"); + DependencyProperty dp = ((XamlPropertyNode)n).DP; + Type typeAttachedTo = dp.OwnerType; + string propertyName = ((XamlPropertyNode)n).PropertyName; + + CreateDependencyProperty(typeAttachedTo, propertyName, dp.PropertyType); + } else if (n is XamlClrEventNode) { + Debug.WriteLine("ObjectWriter: event"); + CreateEvent((EventInfo)((XamlClrEventNode)n).EventMember); + CreateEventDelegate(((XamlClrEventNode)n).Value, ((EventInfo)((XamlClrEventNode)n).EventMember).EventHandlerType); + EndEvent(); + + } else if (n is XamlTextNode && ((XamlTextNode)n).mode == XamlParseMode.Object){ + Debug.WriteLine("ObjectWriter: text for object"); + CreateObjectText(((XamlTextNode)n).TextContent); + } else if (n is XamlTextNode && ((XamlTextNode)n).mode == XamlParseMode.Property){ + Debug.WriteLine("ObjectWriter: text for property"); + Debug.WriteLine("THINGTYPE = " + peek().GetType()); + CreatePropertyText(((XamlTextNode)n).TextContent, ((PropertyInfo)peek()).PropertyType); + EndProperty(); + } else if (n is XamlTextNode && ((XamlTextNode)n).mode == XamlParseMode.DependencyProperty){ + Debug.WriteLine("ObjectWriter: text for dependency property"); + string propertyName = (string)peek(); + Type attachedTo = (Type)peek(1); + CreateDependencyPropertyText(((XamlTextNode)n).TextContent, ((DependencyProperty)attachedTo.GetField(propertyName + "Property").GetValue(null)).PropertyType); + EndDependencyProperty(); + } else if (n is XamlPropertyComplexEndNode) { + Debug.WriteLine("ObjectWriter: end complex property"); + Debug.WriteLine("ObjectWriter: final type is " + ((XamlPropertyComplexEndNode)n).finalType); + EndPropertyObject(((XamlPropertyComplexEndNode)n).finalType); + EndProperty(); + } else if (n is XamlElementEndNode) { + Debug.WriteLine("ObjectWriter: end element"); + if (!((XamlElementEndNode)n).propertyObject) + EndObject(); + } else if (n is XamlDocumentEndNode) { + Debug.WriteLine("ObjectWriter: end document"); + Finish(); + } else { + throw new Exception("Unknown node " + n.GetType()); + } + } + } + + + public void CreateTopLevel(Type parent, string className) + { + instance = Activator.CreateInstance(parent); + push(instance); + } + + public void CreateObject(Type type, string varName) + { + Object o = Activator.CreateInstance(type); + ((IAddChild)peek()).AddChild(o); + push(o); + } + + public void CreateProperty(PropertyInfo property) + { + push(property); + } + + // top of stack is a reference to an object + // pushes a reference to the event + public void CreateEvent(EventInfo evt) + { + push(evt); + } + + public void CreateDependencyProperty(Type attachedTo, string propertyName, Type propertyType) + { + push(attachedTo); + push(propertyName); + } + + public void EndDependencyProperty() + { + object value = pop(); + string propertyName = (string)pop(); + Type attachedTo = (Type)pop(); + + MethodInfo setter = attachedTo.GetMethod("Set" + propertyName); + setter.Invoke(null, new object[] { peek(), value}); + } + + public void CreateObjectText(string text) + { + ((IAddChild)peek()).AddText(text); + } + + // top of stack is reference to an event + public void CreateEventDelegate(string functionName, Type eventDelegateType) + { + EventInfo e = (EventInfo)peek(); + object o = peek(1); + e.AddEventHandler(o, Delegate.CreateDelegate(o.GetType(), o, functionName)); + } + // top of stack is reference to a property + public void CreatePropertyDelegate(string functionName, Type propertyType) + { + PropertyInfo p = (PropertyInfo)peek(); + object o = peek(1); + p.SetValue(o, Delegate.CreateDelegate(o.GetType(), o, functionName), null); + } + + public void CreatePropertyText(string text, Type propertyType) + { + object value = text; + if (propertyType != typeof(string)) { + TypeConverter tc = TypeDescriptor.GetConverter(propertyType); + value = tc.ConvertFromString(text); + } + PropertyInfo p = (PropertyInfo)peek(); + object o = peek(1); + p.SetValue(o, value, null); + } + + public void CreatePropertyObject(Type type, string name) + { + object value = Activator.CreateInstance(type); + Debug.WriteLine("ObjectWriter CREATING PROPERTY OBJECT of type" + type); + push(value); + } + public void EndPropertyObject(Type destType) + { + object value = pop(); + Type sourceType = value.GetType(); + Debug.WriteLine("ObjectWriter: EndPropertyObject has a " + value + value.GetType() + ", needs a " + destType); + if (destType != sourceType && !sourceType.IsSubclassOf(destType)) { + TypeConverter tc = TypeDescriptor.GetConverter(destType); + value = tc.ConvertFrom(value); + } + PropertyInfo p = (PropertyInfo)peek(); + object o = peek(1); + p.SetValue(o, value, null); + } + + // top of stack is reference to an attached property + public void CreateDependencyPropertyText(string text, Type propertyType) + { + object value = text; + if (propertyType != typeof(string)) { + TypeConverter tc = TypeDescriptor.GetConverter(propertyType); + value = tc.ConvertFromString(text); + } + push(value); + } + + public void EndObject() + { + pop(); + } + + public void EndProperty() + { + pop(); + } + + public void EndEvent() + { + pop(); + } + + public void Finish() + { + } + + public void CreateCode(string code) + { + throw new NotImplementedException(); + } + + private object peek() + { + return peek(0); + } + private object peek(int i) + { + return objects[objects.Count - 1 - i]; + } + private object pop() + { + object v = objects[objects.Count - 1]; + objects.RemoveAt(objects.Count - 1); + Debug.WriteLine("ObjectWriter POPPING"); + return v; + } + private void push(object v) + { + Debug.WriteLine("ObjectWriter PUSHING " + v); + objects.Add(v); + } + } +} |