2010-04-06 Jb Evain <jbevain@novell.com>
[mcs.git] / class / System.Design / System.ComponentModel.Design.Serialization / RootCodeDomSerializer.cs
blob55791e9af3a61e1f68d6d0d0baca9c27ed4b00f3
1 //
2 // System.ComponentModel.Design.Serialization.RootCodeDomSerializer
3 //
4 // Authors:
5 // Ivan N. Zlatev (contact i-nZ.net)
6 //
7 // (C) 2007 Ivan N. Zlatev
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 #if NET_2_0
32 using System;
33 using System.Collections;
34 using System.Collections.Generic;
35 using System.ComponentModel;
36 using System.ComponentModel.Design;
38 using System.CodeDom;
40 namespace System.ComponentModel.Design.Serialization
42 internal class RootCodeDomSerializer : CodeDomSerializer
45 internal class CodeMap
48 private string _className;
49 private Type _classType;
50 private List<CodeMemberField> _fields;
51 private CodeStatementCollection _initializers;
52 private CodeStatementCollection _begin;
53 private CodeStatementCollection _default;
54 private CodeStatementCollection _end;
57 public CodeMap (Type classType, string className)
59 if (classType == null)
60 throw new ArgumentNullException ("classType");
61 if (className == null)
62 throw new ArgumentNullException ("className");
64 _classType = classType;
65 _className = className;
66 _fields = new List<CodeMemberField> ();
67 _initializers = new CodeStatementCollection ();
68 _begin = new CodeStatementCollection ();
69 _default = new CodeStatementCollection ();
70 _end = new CodeStatementCollection ();
73 public void AddField (CodeMemberField field)
75 _fields.Add (field);
78 public void Add (CodeStatementCollection statements)
80 foreach (CodeStatement statement in statements)
81 this.Add (statement);
84 public void Add (CodeStatement statement)
86 if (statement.UserData["statement-order"] == null)
87 _default.Add (statement);
88 else if ((string)statement.UserData["statement-order"] == "initializer")
89 _initializers.Add (statement);
90 else if ((string)statement.UserData["statement-order"] == "begin")
91 _begin.Add (statement);
92 else if ((string)statement.UserData["statement-order"] == "end")
93 _end.Add (statement);
97 class Type : BaseType
99 #region Windows Form Designer generated code
101 private void InitializeComponent ()
103 // statement-order:
104 initializer
105 pre-begin - e.g: // ComponentName
106 begin - e.g: SuspendLayout
107 default
108 end - e.g: ResumeLayout
109 post-end
112 private field1;
113 private field2;
115 #endregion
119 public CodeTypeDeclaration GenerateClass ()
121 CodeTypeDeclaration clas = new CodeTypeDeclaration (_className);
122 clas.BaseTypes.Add (_classType);
124 clas.StartDirectives.Add (new CodeRegionDirective (CodeRegionMode.Start, "Windows Form Designer generated code"));
126 CodeMemberMethod initialize = new CodeMemberMethod ();
127 initialize.Name = "InitializeComponent";
128 initialize.ReturnType = new CodeTypeReference (typeof (void));
129 initialize.Attributes = MemberAttributes.Private;
131 initialize.Statements.AddRange (_initializers);
132 initialize.Statements.AddRange (_begin);
133 initialize.Statements.AddRange (_default);
134 initialize.Statements.AddRange (_end);
136 clas.Members.Add (initialize);
138 foreach (CodeMemberField field in _fields)
139 clas.Members.Add (field);
141 clas.EndDirectives.Add (new CodeRegionDirective (CodeRegionMode.End, null));
143 return clas;
146 public void Clear ()
148 _fields.Clear ();
149 _initializers.Clear ();
150 _begin.Clear ();
151 _default.Clear ();
152 _end.Clear ();
157 private CodeMap _codeMap;
159 public RootCodeDomSerializer ()
163 public override object Serialize (IDesignerSerializationManager manager, object value)
165 if (manager == null)
166 throw new ArgumentNullException ("manager");
167 if (value == null)
168 throw new ArgumentNullException ("value");
170 if (_codeMap == null)
171 _codeMap = new CodeMap (value.GetType (), manager.GetName (value));
172 _codeMap.Clear ();
174 RootContext rootContext = new RootContext (new CodeThisReferenceExpression (), value);
175 manager.Context.Push (rootContext);
177 this.SerializeComponents (manager, ((IComponent) value).Site.Container.Components, (IComponent) value);
179 // Serialize root component
181 CodeStatementCollection statements = new CodeStatementCollection ();
182 statements.Add (new CodeCommentStatement (String.Empty));
183 statements.Add (new CodeCommentStatement (manager.GetName (value)));
184 statements.Add (new CodeCommentStatement (String.Empty));
185 // Note that during the serialization process below ComponentCodeDomSerializer
186 // will be invoked to serialize the rootcomponent during expression serialization.
187 // It will check for RootContext and return that.
188 base.SerializeProperties (manager, statements, value, new Attribute[0]);
189 base.SerializeEvents (manager, statements, value, new Attribute[0]);
190 _codeMap.Add (statements);
192 manager.Context.Pop ();
193 return _codeMap.GenerateClass ();
196 private void SerializeComponents (IDesignerSerializationManager manager, ICollection components, IComponent rootComponent)
198 foreach (IComponent component in components) {
199 if (!Object.ReferenceEquals (component, rootComponent))
200 SerializeComponent (manager, component);
204 private void SerializeComponent (IDesignerSerializationManager manager, IComponent component)
206 CodeDomSerializer serializer = base.GetSerializer (manager, component) as CodeDomSerializer; // ComponentCodeDomSerializer
207 if (serializer != null) {
208 this._codeMap.AddField (new CodeMemberField (component.GetType (), manager.GetName (component)));
209 // statements can be a CodeExpression if the full serialization has been completed prior
210 // to this serialization call (e.g when it is requested during the serialization of another
211 // component.
213 CodeStatementCollection statements = serializer.Serialize (manager, component) as CodeStatementCollection;
214 if (statements != null)
215 _codeMap.Add (statements);
216 CodeStatement statement = serializer.Serialize (manager, component) as CodeStatement;
217 if (statement != null)
218 _codeMap.Add (statement);
222 public override object Deserialize (IDesignerSerializationManager manager, object codeObject)
224 CodeTypeDeclaration declaration = (CodeTypeDeclaration) codeObject;
225 Type rootType = manager.GetType (declaration.BaseTypes[0].BaseType);
226 object root = manager.CreateInstance (rootType, null, declaration.Name, true);
228 RootContext rootContext = new RootContext (new CodeThisReferenceExpression (), root);
229 manager.Context.Push (rootContext);
231 CodeMemberMethod initComponentMethod = GetInitializeMethod (declaration);
232 if (initComponentMethod == null)
233 throw new InvalidOperationException ("InitializeComponent method is missing in: " + declaration.Name);
235 foreach (CodeStatement statement in initComponentMethod.Statements)
236 base.DeserializeStatement (manager, statement);
238 manager.Context.Pop ();
239 return root;
242 private CodeMemberMethod GetInitializeMethod (CodeTypeDeclaration declaration)
244 CodeMemberMethod method = null;
245 foreach (CodeTypeMember member in declaration.Members) {
246 method = member as CodeMemberMethod;
247 if (method != null && method.Name == "InitializeComponent")
248 break;
250 return method;
254 #endif