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.
33 using System
.Collections
;
34 using System
.Collections
.Generic
;
35 using System
.ComponentModel
;
36 using System
.ComponentModel
.Design
;
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
)
78 public void Add (CodeStatementCollection statements
)
80 foreach (CodeStatement statement
in statements
)
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")
99 #region Windows Form Designer generated code
101 private void InitializeComponent ()
105 pre-begin - e.g: // ComponentName
106 begin - e.g: SuspendLayout
108 end - e.g: ResumeLayout
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));
149 _initializers
.Clear ();
157 private CodeMap _codeMap
;
159 public RootCodeDomSerializer ()
163 public override object Serialize (IDesignerSerializationManager manager
, object value)
166 throw new ArgumentNullException ("manager");
168 throw new ArgumentNullException ("value");
170 if (_codeMap
== null)
171 _codeMap
= new CodeMap (value.GetType (), manager
.GetName (value));
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
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 ();
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")