2 // System.ComponentModel.Design.Serialization.CodeDomDesignerLoader
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
.ComponentModel
;
35 using System
.ComponentModel
.Design
;
38 using System
.CodeDom
.Compiler
;
40 namespace System
.ComponentModel
.Design
.Serialization
42 public abstract class CodeDomDesignerLoader
: BasicDesignerLoader
, INameCreationService
, IDesignerSerializationService
44 private CodeDomSerializer _rootSerializer
;
46 protected CodeDomDesignerLoader ()
50 protected override void Initialize ()
53 base.LoaderHost
.AddService (typeof (IDesignerSerializationService
), this);
54 base.LoaderHost
.AddService (typeof (INameCreationService
), this);
55 base.LoaderHost
.AddService (typeof (ComponentSerializationService
), new
56 CodeDomComponentSerializationService (base.LoaderHost
));
57 if (this.TypeResolutionService
!= null &&
58 LoaderHost
.GetService (typeof (ITypeResolutionService
)) == null)
59 LoaderHost
.AddService (typeof (ITypeResolutionService
), this.TypeResolutionService
);
60 IDesignerSerializationManager manager
= base.LoaderHost
.GetService (typeof (IDesignerSerializationManager
)) as IDesignerSerializationManager
;
62 manager
.AddSerializationProvider (CodeDomSerializationProvider
.Instance
);
65 protected override bool IsReloadNeeded ()
67 if (this.CodeDomProvider
is ICodeDomDesignerReload
)
68 return ((ICodeDomDesignerReload
) CodeDomProvider
).ShouldReloadDesigner (Parse ());
69 return base.IsReloadNeeded ();
72 protected override void PerformLoad (IDesignerSerializationManager manager
)
75 throw new ArgumentNullException ("manager");
77 CodeCompileUnit document
= this.Parse ();
79 throw new NotSupportedException ("The language did not provide a code parser for this file");
81 string namespaceName
= null;
82 CodeTypeDeclaration rootDocument
= GetFirstCodeTypeDecl (document
, out namespaceName
);
83 if (rootDocument
== null)
84 throw new InvalidOperationException ("Cannot find a declaration in a namespace to load.");
86 _rootSerializer
= manager
.GetSerializer (manager
.GetType (rootDocument
.BaseTypes
[0].BaseType
),
87 typeof (RootCodeDomSerializer
)) as CodeDomSerializer
;
88 if (_rootSerializer
== null)
89 throw new InvalidOperationException ("Serialization not supported for this class");
91 _rootSerializer
.Deserialize (manager
, rootDocument
);
93 base.SetBaseComponentClassName (namespaceName
+ "." + rootDocument
.Name
);
96 private CodeTypeDeclaration
GetFirstCodeTypeDecl (CodeCompileUnit document
, out string namespaceName
)
100 foreach (CodeNamespace namesp
in document
.Namespaces
) {
101 foreach (CodeTypeDeclaration declaration
in namesp
.Types
) {
102 if (declaration
.IsClass
) {
103 namespaceName
= namesp
.Name
;
111 protected override void PerformFlush (IDesignerSerializationManager manager
)
113 if (_rootSerializer
!= null) {
114 CodeTypeDeclaration typeDecl
= (CodeTypeDeclaration
) _rootSerializer
.Serialize (manager
,
115 base.LoaderHost
.RootComponent
);
116 this.Write (MergeTypeDeclWithCompileUnit (typeDecl
, this.Parse ()));
120 // Will either add the class or replace an existing class
121 // with the one from GenerateClass ()
123 private CodeCompileUnit
MergeTypeDeclWithCompileUnit (CodeTypeDeclaration typeDecl
, CodeCompileUnit unit
)
125 CodeNamespace namespac
= null;
128 foreach (CodeNamespace namesp
in unit
.Namespaces
) {
129 for (int i
=0; i
< namesp
.Types
.Count
; i
++) {
130 if (namesp
.Types
[i
].IsClass
) {
138 namespac
.Types
.RemoveAt (typeIndex
);
140 namespac
.Types
.Add (typeDecl
);
145 protected override void OnBeginLoad ()
149 IComponentChangeService service
= base.GetService (typeof (IComponentChangeService
)) as IComponentChangeService
;
151 service
.ComponentRename
+= this.OnComponentRename_EventHandler
;
154 protected override void OnBeginUnload ()
156 base.OnBeginUnload ();
158 IComponentChangeService service
= base.GetService (typeof (IComponentChangeService
)) as IComponentChangeService
;
160 service
.ComponentRename
-= this.OnComponentRename_EventHandler
;
163 protected override void OnEndLoad (bool successful
, ICollection errors
)
165 base.OnEndLoad (successful
, errors
);
166 // XXX: msdn says overriden
169 private void OnComponentRename_EventHandler (object sender
, ComponentRenameEventArgs args
)
171 this.OnComponentRename (args
.Component
, args
.OldName
, args
.NewName
);
174 // MSDN says that here one should raise ComponentRename event and that's nonsense.
176 protected virtual void OnComponentRename (object component
, string oldName
, string newName
)
178 // What shall we do with the drunken sailor,
179 // what shall we do with the drunken sailor early in the morning?
182 protected abstract CodeDomProvider CodeDomProvider { get; }
183 protected abstract ITypeResolutionService TypeResolutionService { get; }
184 protected abstract CodeCompileUnit
Parse ();
185 protected abstract void Write (CodeCompileUnit unit
);
187 public override void Dispose ()
192 #region INameCreationService implementation
194 // very simplistic implementation to generate names like "button1", "someControl2", etc
196 string INameCreationService
.CreateName (IContainer container
, Type dataType
)
198 if (dataType
== null)
199 throw new ArgumentNullException ("dataType");
201 string name
= dataType
.Name
;
202 char lower
= Char
.ToLower (name
[0]);
203 name
= name
.Remove (0, 1);
204 name
= name
.Insert (0, Char
.ToString (lower
));
210 if (container
!= null && container
.Components
[name
+ uniqueId
] != null) {
214 name
= name
+ uniqueId
;
218 if (this.CodeDomProvider
!= null)
219 name
= CodeDomProvider
.CreateValidIdentifier (name
);
224 bool INameCreationService
.IsValidName (string name
)
227 throw new ArgumentNullException ("name");
230 if (base.LoaderHost
!= null && base.LoaderHost
.Container
.Components
[name
] != null) {
233 if (this.CodeDomProvider
!= null) {
234 valid
= CodeDomProvider
.IsValidIdentifier (name
);
236 if (name
.Trim().Length
== 0)
238 foreach (char c
in name
) {
239 if (!Char
.IsLetterOrDigit (c
)) {
250 void INameCreationService
.ValidateName (string name
)
252 if (!((INameCreationService
) this).IsValidName (name
))
253 throw new ArgumentException ("Invalid name '" + name
+ "'");
258 #region IDesignerSerializationService implementation
260 ICollection IDesignerSerializationService
.Deserialize (object serializationData
)
262 if (serializationData
== null)
263 throw new ArgumentNullException ("serializationData");
265 ComponentSerializationService service
= LoaderHost
.GetService (typeof (ComponentSerializationService
)) as ComponentSerializationService
;
266 SerializationStore store
= serializationData
as SerializationStore
;
267 if (service
!= null && serializationData
!= null)
268 return service
.Deserialize (store
, this.LoaderHost
.Container
);
269 return new object[0];
272 object IDesignerSerializationService
.Serialize (ICollection objects
)
275 throw new ArgumentNullException ("objects");
277 ComponentSerializationService service
= LoaderHost
.GetService (typeof (ComponentSerializationService
)) as ComponentSerializationService
;
278 if (service
!= null) {
279 SerializationStore store
= service
.CreateStore ();
280 foreach (object o
in objects
)
281 service
.Serialize (store
, o
);