2 // System.ComponentModel.Design.Serialization.RootCodeDomSerializer
5 // Ivan N. Zlatev (contact i-nZ.net)
7 // (C) 2007 Ivan N. Zlatev
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.
32 using System.Collections;
33 using System.Collections.Generic;
34 using System.ComponentModel;
35 using System.ComponentModel.Design;
39 namespace System.ComponentModel.Design.Serialization
41 internal class RootCodeDomSerializer : CodeDomSerializer
44 internal class CodeMap
47 private string _className;
48 private Type _classType;
49 private List<CodeMemberField> _fields;
50 private CodeStatementCollection _initializers;
51 private CodeStatementCollection _begin;
52 private CodeStatementCollection _default;
53 private CodeStatementCollection _end;
56 public CodeMap (Type classType, string className)
58 if (classType == null)
59 throw new ArgumentNullException ("classType");
60 if (className == null)
61 throw new ArgumentNullException ("className");
63 _classType = classType;
64 _className = className;
65 _fields = new List<CodeMemberField> ();
66 _initializers = new CodeStatementCollection ();
67 _begin = new CodeStatementCollection ();
68 _default = new CodeStatementCollection ();
69 _end = new CodeStatementCollection ();
72 public void AddField (CodeMemberField field)
77 public void Add (CodeStatementCollection statements)
79 foreach (CodeStatement statement in statements)
83 public void Add (CodeStatement statement)
85 if (statement.UserData["statement-order"] == null)
86 _default.Add (statement);
87 else if ((string)statement.UserData["statement-order"] == "initializer")
88 _initializers.Add (statement);
89 else if ((string)statement.UserData["statement-order"] == "begin")
90 _begin.Add (statement);
91 else if ((string)statement.UserData["statement-order"] == "end")
98 #region Windows Form Designer generated code
100 private void InitializeComponent ()
104 pre-begin - e.g: // ComponentName
105 begin - e.g: SuspendLayout
107 end - e.g: ResumeLayout
118 public CodeTypeDeclaration GenerateClass ()
120 CodeTypeDeclaration clas = new CodeTypeDeclaration (_className);
121 clas.BaseTypes.Add (_classType);
123 clas.StartDirectives.Add (new CodeRegionDirective (CodeRegionMode.Start, "Windows Form Designer generated code"));
125 CodeMemberMethod initialize = new CodeMemberMethod ();
126 initialize.Name = "InitializeComponent";
127 initialize.ReturnType = new CodeTypeReference (typeof (void));
128 initialize.Attributes = MemberAttributes.Private;
130 initialize.Statements.AddRange (_initializers);
131 initialize.Statements.AddRange (_begin);
132 initialize.Statements.AddRange (_default);
133 initialize.Statements.AddRange (_end);
135 clas.Members.Add (initialize);
137 foreach (CodeMemberField field in _fields)
138 clas.Members.Add (field);
140 clas.EndDirectives.Add (new CodeRegionDirective (CodeRegionMode.End, null));
148 _initializers.Clear ();
156 private CodeMap _codeMap;
158 public RootCodeDomSerializer ()
162 public override object Serialize (IDesignerSerializationManager manager, object value)
165 throw new ArgumentNullException ("manager");
167 throw new ArgumentNullException ("value");
169 if (_codeMap == null)
170 _codeMap = new CodeMap (value.GetType (), manager.GetName (value));
173 RootContext rootContext = new RootContext (new CodeThisReferenceExpression (), value);
174 manager.Context.Push (rootContext);
176 this.SerializeComponents (manager, ((IComponent) value).Site.Container.Components, (IComponent) value);
178 // Serialize root component
180 CodeStatementCollection statements = new CodeStatementCollection ();
181 statements.Add (new CodeCommentStatement (String.Empty));
182 statements.Add (new CodeCommentStatement (manager.GetName (value)));
183 statements.Add (new CodeCommentStatement (String.Empty));
184 // Note that during the serialization process below ComponentCodeDomSerializer
185 // will be invoked to serialize the rootcomponent during expression serialization.
186 // It will check for RootContext and return that.
187 base.SerializeProperties (manager, statements, value, new Attribute[0]);
188 base.SerializeEvents (manager, statements, value, new Attribute[0]);
189 _codeMap.Add (statements);
191 manager.Context.Pop ();
192 return _codeMap.GenerateClass ();
195 private void SerializeComponents (IDesignerSerializationManager manager, ICollection components, IComponent rootComponent)
197 foreach (IComponent component in components) {
198 if (!Object.ReferenceEquals (component, rootComponent))
199 SerializeComponent (manager, component);
203 private void SerializeComponent (IDesignerSerializationManager manager, IComponent component)
205 CodeDomSerializer serializer = base.GetSerializer (manager, component) as CodeDomSerializer; // ComponentCodeDomSerializer
206 if (serializer != null) {
207 this._codeMap.AddField (new CodeMemberField (component.GetType (), manager.GetName (component)));
208 // statements can be a CodeExpression if the full serialization has been completed prior
209 // to this serialization call (e.g when it is requested during the serialization of another
212 CodeStatementCollection statements = serializer.Serialize (manager, component) as CodeStatementCollection;
213 if (statements != null)
214 _codeMap.Add (statements);
215 CodeStatement statement = serializer.Serialize (manager, component) as CodeStatement;
216 if (statement != null)
217 _codeMap.Add (statement);
221 public override object Deserialize (IDesignerSerializationManager manager, object codeObject)
223 CodeTypeDeclaration declaration = (CodeTypeDeclaration) codeObject;
224 Type rootType = manager.GetType (declaration.BaseTypes[0].BaseType);
225 object root = manager.CreateInstance (rootType, null, declaration.Name, true);
227 RootContext rootContext = new RootContext (new CodeThisReferenceExpression (), root);
228 manager.Context.Push (rootContext);
230 CodeMemberMethod initComponentMethod = GetInitializeMethod (declaration);
231 if (initComponentMethod == null)
232 throw new InvalidOperationException ("InitializeComponent method is missing in: " + declaration.Name);
234 foreach (CodeStatement statement in initComponentMethod.Statements)
235 base.DeserializeStatement (manager, statement);
237 manager.Context.Pop ();
241 private CodeMemberMethod GetInitializeMethod (CodeTypeDeclaration declaration)
243 CodeMemberMethod method = null;
244 foreach (CodeTypeMember member in declaration.Members) {
245 method = member as CodeMemberMethod;
246 if (method != null && method.Name == "InitializeComponent")