From ebb89a2e19569488799e188fabfda51b984c1bae Mon Sep 17 00:00:00 2001 From: Iain McCoy Date: Sun, 3 Jul 2005 03:32:25 +0000 Subject: 2005-07-03 Iain McCoy * Mono.Windows.Serialization/CodeWriter.cs: use CodeDom to do code generation * Mono.Windows.Serialization/CodeWriter.cs: * Mono.Windows.Serialization/XamlWriter.cs: * Mono.Windows.Serialization/XamlParser.cs: initial TypeConverter support svn path=/trunk/mcs/; revision=46885 --- mcs/class/PresentationFramework/ChangeLog | 9 ++ mcs/class/PresentationFramework/Makefile | 2 +- .../Mono.Windows.Serialization/CodeWriter.cs | 118 ++++++++++++++++----- .../Mono.Windows.Serialization/XamlParser.cs | 44 ++++++-- .../Mono.Windows.Serialization/XamlWriter.cs | 4 +- 5 files changed, 141 insertions(+), 36 deletions(-) (limited to 'mcs/class/PresentationFramework') diff --git a/mcs/class/PresentationFramework/ChangeLog b/mcs/class/PresentationFramework/ChangeLog index d2e6b96d74d..b8ce3c41d22 100644 --- a/mcs/class/PresentationFramework/ChangeLog +++ b/mcs/class/PresentationFramework/ChangeLog @@ -1,3 +1,12 @@ +2005-07-03 Iain McCoy + + * Mono.Windows.Serialization/CodeWriter.cs: use CodeDom to do code + generation + * Mono.Windows.Serialization/CodeWriter.cs: + * Mono.Windows.Serialization/XamlWriter.cs: + * Mono.Windows.Serialization/XamlParser.cs: initial TypeConverter + support + 2005-07-02 Iain McCoy * whole folder: implementation of Xaml-related namespaces diff --git a/mcs/class/PresentationFramework/Makefile b/mcs/class/PresentationFramework/Makefile index c7011cf42ec..f04f16b745e 100644 --- a/mcs/class/PresentationFramework/Makefile +++ b/mcs/class/PresentationFramework/Makefile @@ -3,7 +3,7 @@ include ../../build/rules.make LIBRARY = PresentationFramework.dll -LIB_MCS_FLAGS = -r:System.Xml.dll -r:WindowsBase.dll +LIB_MCS_FLAGS = -r:System.Xml.dll -r:WindowsBase.dll -r:System.dll NO_TEST = yes include ../../build/library.make diff --git a/mcs/class/PresentationFramework/Mono.Windows.Serialization/CodeWriter.cs b/mcs/class/PresentationFramework/Mono.Windows.Serialization/CodeWriter.cs index 1258074f474..16cb2d0aa4a 100644 --- a/mcs/class/PresentationFramework/Mono.Windows.Serialization/CodeWriter.cs +++ b/mcs/class/PresentationFramework/Mono.Windows.Serialization/CodeWriter.cs @@ -29,6 +29,8 @@ using System; using System.IO; using System.Collections; +using System.CodeDom; +using System.CodeDom.Compiler; namespace Mono.Windows.Serialization { public class CodeWriter : XamlWriter { @@ -36,20 +38,44 @@ namespace Mono.Windows.Serialization { ArrayList objects = new ArrayList(); Hashtable nameClashes = new Hashtable(); int tempIndex = 0; + + CodeCompileUnit code; + CodeConstructor constructor; + // pushes: the code writer public CodeWriter(TextWriter writer) { this.writer = writer; + code = new CodeCompileUnit(); + objects.Add(code); } - + + // pushes: a CodeVariableReferenceExpression to the present + // instance public void CreateTopLevel(string parentName, string className) { Type parent = Type.GetType(parentName); - writer.WriteLine(className + " extends " + - parent.Namespace + "." + parent.Name); - objects.Add("this"); + int endNamespaceName = className.LastIndexOf("."); + string clrNamespace; + if (endNamespaceName < 0) + clrNamespace = "DefaultNamespace"; + else + clrNamespace = className.Substring(0, + endNamespaceName); + CodeNamespace ns = new CodeNamespace(clrNamespace); + ((CodeCompileUnit)objects[0]).Namespaces.Add(ns); + + CodeTypeDeclaration type = new CodeTypeDeclaration(className); + type.BaseTypes.Add(new CodeTypeReference(parent)); + constructor = new CodeConstructor(); + type.Members.Add(constructor); + ns.Types.Add(type); + + objects.Add(new CodeThisReferenceExpression()); } - + + // bottom of stack holds CodeVariableReferenceExpression + // pushes a reference to the new current type public void CreateObject(string typeName) { Type type = Type.GetType(typeName); @@ -65,56 +91,94 @@ namespace Mono.Windows.Serialization { nameClashes[varName] = 1 + (int)nameClashes[varName]; varName += (int)nameClashes[varName]; } - - writer.WriteLine(type.Name + " " + varName); - writer.WriteLine(objects[objects.Count - 1] + ".AddChild(" + varName + ")"); - objects.Add(varName); + + CodeVariableDeclarationStatement declaration = + new CodeVariableDeclarationStatement(type, varName); + CodeVariableReferenceExpression varRef = new CodeVariableReferenceExpression(varName); + CodeMethodInvokeExpression addChild = new CodeMethodInvokeExpression( + (CodeExpression)objects[objects.Count - 1], + "AddChild", + varRef); + constructor.Statements.Add(declaration); + constructor.Statements.Add(addChild); + objects.Add(varRef); } + // top of stack is a reference to an object + // pushes a reference to the property public void CreateProperty(string propertyName) { - string varName = (string)objects[objects.Count - 1]; - string prop = varName + "." + propertyName; + CodePropertyReferenceExpression prop = new CodePropertyReferenceExpression( + (CodeExpression)objects[objects.Count - 1], + propertyName); objects.Add(prop); } + // top of stack is a reference to an object + // pushes the name of the instance to attach to, the name of + // the property, and a reference to an object public void CreateAttachedProperty(string attachedTo, string propertyName, string typeName) { + // need to: Type t = Type.GetType(typeName); - objects.Add(attachedTo); - objects.Add(propertyName); string name = "temp"; if (tempIndex != 0) name += tempIndex; - writer.WriteLine(t.Name + " " + name); - objects.Add(name); + CodeVariableDeclarationStatement decl = new CodeVariableDeclarationStatement(t, name); + constructor.Statements.Add(decl); + + + CodeMethodInvokeExpression call = new CodeMethodInvokeExpression( + new CodeVariableReferenceExpression(attachedTo), + "Set" + propertyName, + (CodeExpression)objects[objects.Count - 1], + new CodeVariableReferenceExpression(name)); + + objects.Add(call); + objects.Add(new CodeVariableReferenceExpression(name)); } + // pops 2 items: the name of the property, and the object to attach to public void EndAttachedProperty() { - string varName = (string)(objects[objects.Count - 1]); - string propertyName = (string)(objects[objects.Count - 2]); - string attachedTo = (string)(objects[objects.Count - 3]); objects.RemoveAt(objects.Count - 1); + CodeExpression call = (CodeExpression)(objects[objects.Count - 1]); objects.RemoveAt(objects.Count - 1); - objects.RemoveAt(objects.Count - 1); - writer.WriteLine(attachedTo + ".Set" + propertyName + "(" + objects[objects.Count - 1] + ", " + varName + ");"); + constructor.Statements.Add(call); } + // top of stack must be an object reference public void CreateElementText(string text) { - writer.WriteLine(objects[objects.Count - 1] + ".AddText(\"" + text +"\")"); + CodeVariableReferenceExpression var = (CodeVariableReferenceExpression)objects[objects.Count - 1]; + CodeMethodInvokeExpression call = new CodeMethodInvokeExpression( + var, + "AddText", + new CodePrimitiveExpression(text)); + constructor.Statements.Add(call); } - public void CreatePropertyText(string text) + // top of stack is reference to a property + public void CreatePropertyText(string text, string converter) { - writer.WriteLine(objects[objects.Count - 1] + " = " + - "\"" + text + "\""); + CreateAttachedPropertyText(text, converter); } - public void CreateAttachedPropertyText(string text) + public void CreateAttachedPropertyText(string text, string converter) { - writer.WriteLine(objects[objects.Count - 1] + " = " + text); + CodeExpression expr = new CodePrimitiveExpression(text); + if (converter != null) { + Type t = Type.GetType(converter); + expr = new CodeMethodInvokeExpression( + new CodeTypeReferenceExpression(t), + "ConvertFromString", + expr); + } + CodeAssignStatement assignment = new CodeAssignStatement( + (CodeExpression)objects[objects.Count - 1], + expr); + + constructor.Statements.Add(assignment); } public void EndObject() @@ -129,6 +193,8 @@ namespace Mono.Windows.Serialization { public void Finish() { + ICodeGenerator generator = (new Microsoft.CSharp.CSharpCodeProvider()).CreateGenerator(); + generator.GenerateCodeFromCompileUnit(code, writer, null); writer.Close(); } } diff --git a/mcs/class/PresentationFramework/Mono.Windows.Serialization/XamlParser.cs b/mcs/class/PresentationFramework/Mono.Windows.Serialization/XamlParser.cs index fd4d8220114..6dbfdfaaa40 100644 --- a/mcs/class/PresentationFramework/Mono.Windows.Serialization/XamlParser.cs +++ b/mcs/class/PresentationFramework/Mono.Windows.Serialization/XamlParser.cs @@ -131,14 +131,43 @@ namespace Mono.Windows.Serialization { void parseText() { - if (currentState.type == CurrentType.Object) + if (currentState.type == CurrentType.Object) { writer.CreateElementText(reader.Value); - else if (currentState.type == CurrentType.AttachedProperty) - writer.CreateAttachedPropertyText(reader.Value); - else - writer.CreatePropertyText(reader.Value); + } else if (currentState.type == CurrentType.AttachedProperty) { + DependencyProperty dp = (DependencyProperty)currentState.obj; + writer.CreateAttachedPropertyText(reader.Value, getTypeConverter(dp.PropertyType)); + } else { + PropertyInfo prop = (PropertyInfo)currentState.obj; + writer.CreatePropertyText(reader.Value, getTypeConverter(prop.PropertyType)); + } } + string getTypeConverter(Type fromType) + { + // TODO: this business setting assembly is frankly + // grotesque. It should just be something along the + // lines of Assembly.Load("System.dll") + Assembly assembly = null; + foreach (Assembly a in AppDomain.CurrentDomain.GetAssemblies()) { + if (a.CodeBase.EndsWith("System.dll")) { + assembly = a; + break; + } + } + + + if (fromType.Namespace == "System" && + fromType.Name == "String") + return null; + string converterName = "System.ComponentModel." + fromType.Name + "Converter,System.dll"; + Console.WriteLine("YY '"+converterName + "'"); + Type converter = assembly.GetType(converterName); + return converter.AssemblyQualifiedName; + // TODO: catch NullReferenceException and do something + // cool + } + + void parseNormalPropertyElement(string propertyName) { // preconditions: currentState.Type == Object @@ -189,7 +218,7 @@ namespace Mono.Windows.Serialization { oldStates.Add(currentState); currentState = new ParserState(); - currentState.obj = propField; + currentState.obj = dp; currentState.type = CurrentType.AttachedProperty; writer.CreateAttachedProperty(attachedTo, propertyName, dp.PropertyType.AssemblyQualifiedName); @@ -238,11 +267,12 @@ namespace Mono.Windows.Serialization { } writer.CreateProperty(propertyName); - writer.CreatePropertyText(reader.Value); + writer.CreatePropertyText(reader.Value, getTypeConverter(prop.PropertyType)); parseEndElement(); } + void parseContextPropertyAttribute() { throw new NotImplementedException("parseContextPropertyAttribute"); diff --git a/mcs/class/PresentationFramework/Mono.Windows.Serialization/XamlWriter.cs b/mcs/class/PresentationFramework/Mono.Windows.Serialization/XamlWriter.cs index 238307af0c6..b4365248c19 100644 --- a/mcs/class/PresentationFramework/Mono.Windows.Serialization/XamlWriter.cs +++ b/mcs/class/PresentationFramework/Mono.Windows.Serialization/XamlWriter.cs @@ -32,9 +32,9 @@ namespace Mono.Windows.Serialization { void CreateObject(string typeName); void CreateProperty(string propertyName); void CreateElementText(string text); - void CreatePropertyText(string text); + void CreatePropertyText(string text, string converter); void CreateAttachedProperty(string attachedTo, string propertyName, string typeName); - void CreateAttachedPropertyText(string text); + void CreateAttachedPropertyText(string text, string converter); void EndObject(); void EndProperty(); void EndAttachedProperty(); -- cgit v1.2.3