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 System.Windows.Serialization;
41 namespace Mono.Windows.Serialization {
42 public class ObjectWriter {
43 public object instance;
44 ArrayList objects = new ArrayList();
46 public static object Parse(XmlTextReader reader)
48 ObjectWriter ow = new ObjectWriter(reader);
51 private ObjectWriter(XmlTextReader reader)
53 XamlParser p = new XamlParser(reader);
59 Debug.WriteLine("ObjectWriter: INCOMING " + n.GetType());
60 if (n is XamlDocumentStartNode) {
61 Debug.WriteLine("ObjectWriter: document begins");
63 } else if (n is XamlElementStartNode && n.Depth == 0) {
64 Debug.WriteLine("ObjectWriter: element begins as top-level");
65 CreateTopLevel(((XamlElementStartNode)n).ElementType, ((XamlElementStartNode)n).name);
66 } else if (n is XamlElementStartNode && peek() is PropertyInfo) {
67 Debug.WriteLine("ObjectWriter: element begins as property value");
68 CreatePropertyObject(((XamlElementStartNode)n).ElementType, ((XamlElementStartNode)n).name);
69 } else if (n is XamlElementStartNode) {
70 Debug.WriteLine("ObjectWriter: element begins");
71 CreateObject(((XamlElementStartNode)n).ElementType, ((XamlElementStartNode)n).name);
72 } else if (n is XamlPropertyNode && ((XamlPropertyNode)n).PropInfo != null) {
73 Debug.WriteLine("ObjectWriter: normal property begins");
74 CreateProperty(((XamlPropertyNode)n).PropInfo);
75 } else if (n is XamlPropertyNode && ((XamlPropertyNode)n).DP != null) {
76 Debug.WriteLine("ObjectWriter: dependency property begins");
77 DependencyProperty dp = ((XamlPropertyNode)n).DP;
78 Type typeAttachedTo = dp.OwnerType;
79 string propertyName = ((XamlPropertyNode)n).PropertyName;
81 CreateDependencyProperty(typeAttachedTo, propertyName, dp.PropertyType);
82 } else if (n is XamlClrEventNode) {
83 Debug.WriteLine("ObjectWriter: event");
84 CreateEvent((EventInfo)((XamlClrEventNode)n).EventMember);
85 CreateEventDelegate(((XamlClrEventNode)n).Value, ((EventInfo)((XamlClrEventNode)n).EventMember).EventHandlerType);
88 } else if (n is XamlTextNode && ((XamlTextNode)n).mode == XamlParseMode.Object){
89 Debug.WriteLine("ObjectWriter: text for object");
90 CreateObjectText(((XamlTextNode)n).TextContent);
91 } else if (n is XamlTextNode && ((XamlTextNode)n).mode == XamlParseMode.Property){
92 Debug.WriteLine("ObjectWriter: text for property");
93 Debug.WriteLine("THINGTYPE = " + peek().GetType());
94 CreatePropertyText(((XamlTextNode)n).TextContent, ((PropertyInfo)peek()).PropertyType);
96 } else if (n is XamlTextNode && ((XamlTextNode)n).mode == XamlParseMode.DependencyProperty){
97 Debug.WriteLine("ObjectWriter: text for dependency property");
98 string propertyName = (string)peek();
99 Type attachedTo = (Type)peek(1);
100 CreateDependencyPropertyText(((XamlTextNode)n).TextContent, ((DependencyProperty)attachedTo.GetField(propertyName + "Property").GetValue(null)).PropertyType);
101 EndDependencyProperty();
102 } else if (n is XamlPropertyComplexEndNode) {
103 Debug.WriteLine("ObjectWriter: end complex property");
104 Debug.WriteLine("ObjectWriter: final type is " + ((XamlPropertyComplexEndNode)n).finalType);
105 EndPropertyObject(((XamlPropertyComplexEndNode)n).finalType);
107 } else if (n is XamlElementEndNode) {
108 Debug.WriteLine("ObjectWriter: end element");
109 if (!((XamlElementEndNode)n).propertyObject)
111 } else if (n is XamlDocumentEndNode) {
112 Debug.WriteLine("ObjectWriter: end document");
115 throw new Exception("Unknown node " + n.GetType());
121 public void CreateTopLevel(Type parent, string className)
123 instance = Activator.CreateInstance(parent);
127 public void CreateObject(Type type, string varName)
129 Object o = Activator.CreateInstance(type);
130 ((IAddChild)peek()).AddChild(o);
134 public void CreateProperty(PropertyInfo property)
139 // top of stack is a reference to an object
140 // pushes a reference to the event
141 public void CreateEvent(EventInfo evt)
146 public void CreateDependencyProperty(Type attachedTo, string propertyName, Type propertyType)
152 public void EndDependencyProperty()
154 object value = pop();
155 string propertyName = (string)pop();
156 Type attachedTo = (Type)pop();
158 MethodInfo setter = attachedTo.GetMethod("Set" + propertyName);
159 setter.Invoke(null, new object[] { peek(), value});
162 public void CreateObjectText(string text)
164 ((IAddChild)peek()).AddText(text);
167 // top of stack is reference to an event
168 public void CreateEventDelegate(string functionName, Type eventDelegateType)
170 EventInfo e = (EventInfo)peek();
172 e.AddEventHandler(o, Delegate.CreateDelegate(o.GetType(), o, functionName));
174 // top of stack is reference to a property
175 public void CreatePropertyDelegate(string functionName, Type propertyType)
177 PropertyInfo p = (PropertyInfo)peek();
179 p.SetValue(o, Delegate.CreateDelegate(o.GetType(), o, functionName), null);
182 public void CreatePropertyText(string text, Type propertyType)
185 if (propertyType != typeof(string)) {
186 TypeConverter tc = TypeDescriptor.GetConverter(propertyType);
187 value = tc.ConvertFromString(text);
189 PropertyInfo p = (PropertyInfo)peek();
191 p.SetValue(o, value, null);
194 public void CreatePropertyObject(Type type, string name)
196 object value = Activator.CreateInstance(type);
197 Debug.WriteLine("ObjectWriter CREATING PROPERTY OBJECT of type" + type);
200 public void EndPropertyObject(Type destType)
202 object value = pop();
203 Type sourceType = value.GetType();
204 Debug.WriteLine("ObjectWriter: EndPropertyObject has a " + value + value.GetType() + ", needs a " + destType);
205 if (destType != sourceType && !sourceType.IsSubclassOf(destType)) {
206 TypeConverter tc = TypeDescriptor.GetConverter(destType);
207 value = tc.ConvertFrom(value);
209 PropertyInfo p = (PropertyInfo)peek();
211 p.SetValue(o, value, null);
214 // top of stack is reference to an attached property
215 public void CreateDependencyPropertyText(string text, Type propertyType)
218 if (propertyType != typeof(string)) {
219 TypeConverter tc = TypeDescriptor.GetConverter(propertyType);
220 value = tc.ConvertFromString(text);
225 public void EndObject()
230 public void EndProperty()
235 public void EndEvent()
244 public void CreateCode(string code)
246 throw new NotImplementedException();
249 private object peek()
253 private object peek(int i)
255 return objects[objects.Count - 1 - i];
259 object v = objects[objects.Count - 1];
260 objects.RemoveAt(objects.Count - 1);
261 Debug.WriteLine("ObjectWriter POPPING");
264 private void push(object v)
266 Debug.WriteLine("ObjectWriter PUSHING " + v);