5 // Iain McCoy (iain@mccoy.id.au)
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 using System.Reflection;
32 using System.Collections;
34 using System.CodeDom.Compiler;
35 using System.ComponentModel;
36 using System.Diagnostics;
38 using Mono.Windows.Serialization;
41 namespace System.Windows.Serialization {
43 private object instance;
44 ArrayList objects = new ArrayList();
46 public static object LoadXml(Stream s)
48 return LoadXml(new XmlTextReader(s));
50 // TODO: this should take a XmlReader in order to be same as MSFT
51 public static object LoadXml(XmlTextReader reader)
53 Parser r = new Parser(reader);
56 private Parser(XmlTextReader reader)
58 XamlParser p = new XamlParser(reader);
64 Debug.WriteLine("ObjectWriter: INCOMING " + n.GetType());
65 if (n is XamlDocumentStartNode) {
66 Debug.WriteLine("ObjectWriter: document begins");
68 } else if (n is XamlElementStartNode && n.Depth == 0) {
69 Debug.WriteLine("ObjectWriter: element begins as top-level");
70 CreateTopLevel(((XamlElementStartNode)n).ElementType, ((XamlElementStartNode)n).name);
71 } else if (n is XamlElementStartNode && peek() is PropertyInfo) {
72 Debug.WriteLine("ObjectWriter: element begins as property value");
73 CreatePropertyObject(((XamlElementStartNode)n).ElementType, ((XamlElementStartNode)n).name);
74 } else if (n is XamlElementStartNode) {
75 Debug.WriteLine("ObjectWriter: element begins");
76 CreateObject(((XamlElementStartNode)n).ElementType, ((XamlElementStartNode)n).name);
77 } else if (n is XamlPropertyNode && ((XamlPropertyNode)n).PropInfo != null) {
78 Debug.WriteLine("ObjectWriter: normal property begins");
79 CreateProperty(((XamlPropertyNode)n).PropInfo);
80 } else if (n is XamlPropertyNode && ((XamlPropertyNode)n).DP != null) {
81 Debug.WriteLine("ObjectWriter: dependency property begins");
82 DependencyProperty dp = ((XamlPropertyNode)n).DP;
83 Type typeAttachedTo = dp.OwnerType;
84 string propertyName = ((XamlPropertyNode)n).PropertyName;
86 CreateDependencyProperty(typeAttachedTo, propertyName, dp.PropertyType);
87 } else if (n is XamlClrEventNode) {
88 Debug.WriteLine("ObjectWriter: event");
89 CreateEvent((EventInfo)((XamlClrEventNode)n).EventMember);
90 CreateEventDelegate(((XamlClrEventNode)n).Value, ((EventInfo)((XamlClrEventNode)n).EventMember).EventHandlerType);
93 } else if (n is XamlTextNode && ((XamlTextNode)n).mode == XamlParseMode.Object){
94 Debug.WriteLine("ObjectWriter: text for object");
95 CreateObjectText(((XamlTextNode)n).TextContent);
96 } else if (n is XamlTextNode && ((XamlTextNode)n).mode == XamlParseMode.Property){
97 Debug.WriteLine("ObjectWriter: text for property");
98 Debug.WriteLine("THINGTYPE = " + peek().GetType());
99 CreatePropertyText(((XamlTextNode)n).TextContent, ((PropertyInfo)peek()).PropertyType);
101 } else if (n is XamlTextNode && ((XamlTextNode)n).mode == XamlParseMode.DependencyProperty){
102 Debug.WriteLine("ObjectWriter: text for dependency property");
103 string propertyName = (string)peek();
104 Type attachedTo = (Type)peek(1);
105 CreateDependencyPropertyText(((XamlTextNode)n).TextContent, ((DependencyProperty)attachedTo.GetField(propertyName + "Property").GetValue(null)).PropertyType);
106 EndDependencyProperty();
107 } else if (n is XamlPropertyComplexEndNode) {
108 Debug.WriteLine("ObjectWriter: end complex property");
109 Debug.WriteLine("ObjectWriter: final type is " + ((XamlPropertyComplexEndNode)n).finalType);
110 EndPropertyObject(((XamlPropertyComplexEndNode)n).finalType);
112 } else if (n is XamlElementEndNode) {
113 Debug.WriteLine("ObjectWriter: end element");
114 if (!((XamlElementEndNode)n).propertyObject)
116 } else if (n is XamlDocumentEndNode) {
117 Debug.WriteLine("ObjectWriter: end document");
120 throw new Exception("Unknown node " + n.GetType());
126 public void CreateTopLevel(Type parent, string className)
128 instance = Activator.CreateInstance(parent);
132 public void CreateObject(Type type, string varName)
134 Object o = Activator.CreateInstance(type);
135 ((IAddChild)peek()).AddChild(o);
139 public void CreateProperty(PropertyInfo property)
144 // top of stack is a reference to an object
145 // pushes a reference to the event
146 public void CreateEvent(EventInfo evt)
151 public void CreateDependencyProperty(Type attachedTo, string propertyName, Type propertyType)
157 public void EndDependencyProperty()
159 object value = pop();
160 string propertyName = (string)pop();
161 Type attachedTo = (Type)pop();
163 MethodInfo setter = attachedTo.GetMethod("Set" + propertyName);
164 setter.Invoke(null, new object[] { peek(), value});
167 public void CreateObjectText(string text)
169 ((IAddChild)peek()).AddText(text);
172 // top of stack is reference to an event
173 public void CreateEventDelegate(string functionName, Type eventDelegateType)
175 EventInfo e = (EventInfo)peek();
177 e.AddEventHandler(o, Delegate.CreateDelegate(o.GetType(), o, functionName));
179 // top of stack is reference to a property
180 public void CreatePropertyDelegate(string functionName, Type propertyType)
182 PropertyInfo p = (PropertyInfo)peek();
184 p.SetValue(o, Delegate.CreateDelegate(o.GetType(), o, functionName), null);
187 public void CreatePropertyText(string text, Type propertyType)
190 if (propertyType != typeof(string)) {
191 TypeConverter tc = TypeDescriptor.GetConverter(propertyType);
192 value = tc.ConvertFromString(text);
194 PropertyInfo p = (PropertyInfo)peek();
196 p.SetValue(o, value, null);
199 public void CreatePropertyObject(Type type, string name)
201 object value = Activator.CreateInstance(type);
202 Debug.WriteLine("ObjectWriter CREATING PROPERTY OBJECT of type" + type);
205 public void EndPropertyObject(Type destType)
207 object value = pop();
208 Type sourceType = value.GetType();
209 Debug.WriteLine("ObjectWriter: EndPropertyObject has a " + value + value.GetType() + ", needs a " + destType);
210 if (destType != sourceType && !sourceType.IsSubclassOf(destType)) {
211 TypeConverter tc = TypeDescriptor.GetConverter(destType);
212 value = tc.ConvertFrom(value);
214 PropertyInfo p = (PropertyInfo)peek();
216 p.SetValue(o, value, null);
219 // top of stack is reference to an attached property
220 public void CreateDependencyPropertyText(string text, Type propertyType)
223 if (propertyType != typeof(string)) {
224 TypeConverter tc = TypeDescriptor.GetConverter(propertyType);
225 value = tc.ConvertFromString(text);
230 public void EndObject()
235 public void EndProperty()
240 public void EndEvent()
249 public void CreateCode(string code)
251 throw new NotImplementedException();
254 private object peek()
258 private object peek(int i)
260 return objects[objects.Count - 1 - i];
264 object v = objects[objects.Count - 1];
265 objects.RemoveAt(objects.Count - 1);
266 Debug.WriteLine("ObjectWriter POPPING");
269 private void push(object v)
271 Debug.WriteLine("ObjectWriter PUSHING " + v);