New tests, update
[mono.git] / mcs / class / System.Design / System.ComponentModel.Design.Serialization / CodeDomSerializerBase.cs
1 //
2 // System.ComponentModel.Design.Serialization.CodeDomSerializerBase
3 //
4 // Authors:      
5 //        Ivan N. Zlatev (contact i-nZ.net)
6 //
7 // (C) 2007 Ivan N. Zlatev
8
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:
17 // 
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
20 // 
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.
28 //
29
30 #if NET_2_0
31
32 using System;
33 using System.Collections;
34 using System.Reflection;
35 using System.ComponentModel;
36 using System.ComponentModel.Design;
37
38 using System.CodeDom;
39
40 namespace System.ComponentModel.Design.Serialization
41 {
42         [EditorBrowsable (EditorBrowsableState.Never)]
43         public abstract class CodeDomSerializerBase
44         {
45
46                 private string _deserializationErrorTrace = null;
47                 private string _deserializationError = null;
48
49                 internal CodeDomSerializerBase ()
50                 {
51                 }
52
53                 private class ExpressionTable : Hashtable // just so that we have a specific type to append to the context stack
54                 {
55                 }
56
57                 protected CodeExpression SerializeToExpression (IDesignerSerializationManager manager, object instance)
58                 {
59                         if (manager == null)
60                                 throw new ArgumentNullException ("manager");
61
62                         CodeExpression expression = null;
63                         if (instance != null)
64                                 expression = this.GetExpression (manager, instance); // 1 - IDesignerSerializationManager.GetExpression
65                         if (expression == null) {
66                                 CodeDomSerializer serializer = this.GetSerializer (manager, instance); // 2 - manager.GetSerializer().Serialize()
67                                 if (serializer != null) {
68                                         object serialized = serializer.Serialize (manager, instance);
69                                         expression = serialized as CodeExpression; // 3 - CodeStatement or CodeStatementCollection
70                                         if (expression == null) {
71                                                 CodeStatement statement = serialized as CodeStatement;
72                                                 CodeStatementCollection statements = serialized as CodeStatementCollection;
73
74                                                 if (statement != null || statements != null) {
75                                                         CodeStatementCollection contextStatements = null;
76
77                                                         StatementContext context = manager.Context[typeof (StatementContext)] as StatementContext;
78                                                         if (context != null && instance != null)
79                                                                 contextStatements = context.StatementCollection[instance];
80
81                                                         if (contextStatements == null)
82                                                                 contextStatements = manager.Context[typeof (CodeStatementCollection)] as CodeStatementCollection;
83
84                                                         if (contextStatements != null) {
85                                                                 if (statements != null)
86                                                                         contextStatements.AddRange (statements);
87                                                                 else
88                                                                         contextStatements.Add (statement);
89                                                         }
90                                                 }
91                                         }
92                                         if (expression == null && instance != null)
93                                                 expression = this.GetExpression (manager, instance); // 4
94                                 }
95                         }
96                         return expression;
97                 }
98
99                 protected CodeDomSerializer GetSerializer (IDesignerSerializationManager manager, object instance)
100                 {
101                         DesignerSerializerAttribute attrInstance, attrType;
102                         attrType = attrInstance = null;
103
104                         CodeDomSerializer serializer = null;
105                         if (instance == null)
106                                 serializer = this.GetSerializer (manager, null);
107                         else {          
108                                 AttributeCollection attributes = TypeDescriptor.GetAttributes (instance);
109                                 foreach (Attribute a in attributes) {
110                                         DesignerSerializerAttribute designerAttr = a as DesignerSerializerAttribute;
111                                         if (designerAttr != null && manager.GetType (designerAttr.SerializerBaseTypeName) == typeof (CodeDomSerializer)) {
112                                                 attrInstance = designerAttr;
113                                                 break;
114                                         }
115                                 }
116         
117                                 attributes = TypeDescriptor.GetAttributes (instance.GetType ());
118                                 foreach (Attribute a in attributes) {
119                                         DesignerSerializerAttribute designerAttr = a as DesignerSerializerAttribute;
120                                         if (designerAttr != null && manager.GetType (designerAttr.SerializerBaseTypeName) == typeof (CodeDomSerializer)) {
121                                                 attrType = designerAttr;
122                                                 break;
123                                         }
124                                 }
125         
126                                 // if there is metadata modification in the instance then create the specified serializer instead of the one
127                                 // in the Type.
128                                 if (attrType != null && attrInstance != null && attrType.SerializerTypeName != attrInstance.SerializerTypeName)
129                                         serializer = Activator.CreateInstance (manager.GetType (attrInstance.SerializerTypeName)) as CodeDomSerializer;
130                                 else
131                                         serializer = this.GetSerializer (manager, instance.GetType ());
132                         }
133
134                         return serializer;
135                 }
136
137                 protected CodeDomSerializer GetSerializer (IDesignerSerializationManager manager, Type instanceType)
138                 {
139                         return manager.GetSerializer (instanceType, typeof (CodeDomSerializer)) as CodeDomSerializer;
140                 }
141
142                 protected CodeExpression GetExpression (IDesignerSerializationManager manager, object instance)
143                 {
144                         if (manager == null)
145                                 throw new ArgumentNullException ("manager");
146                         if (instance == null)
147                                 throw new ArgumentNullException ("instance");
148
149                         CodeExpression expression = null;
150
151                         ExpressionTable expressions = manager.Context[typeof (ExpressionTable)] as ExpressionTable;
152                         if (expressions != null) // 1st try: ExpressionTable
153                                 expression = expressions [instance] as CodeExpression;
154
155                         if (expression == null) { // 2nd try: RootContext
156                                 RootContext context = manager.Context[typeof (RootContext)] as RootContext;
157                                 if (context != null && context.Value == instance)
158                                         expression = context.Expression;
159                         }
160
161                         if (expression == null) { // 3rd try: IReferenceService (instnace.property.property.property
162                                 string name = manager.GetName (instance);
163                                 if (name == null || name.IndexOf (".") == -1) {
164                                         IReferenceService service = manager.GetService (typeof (IReferenceService)) as IReferenceService;
165                                         if (service != null) {
166                                                 name = service.GetName (instance);
167                                                 if (name != null && name.IndexOf (".") != -1) {
168                                                         string[] parts = name.Split (new char[] { ',' });
169                                                         instance = manager.GetInstance (parts[0]);
170                                                         if (instance != null) {
171                                                                 expression = SerializeToExpression (manager, instance);
172                                                                 if (expression != null) {
173                                                                         for (int i=1; i < parts.Length; i++)
174                                                                                 expression = new CodePropertyReferenceExpression (expression, parts[i]);
175                                                                 }
176                                                         }
177                                                 }
178                                         }
179                                 }
180                         }
181                         return expression;
182                 }
183
184                 protected void SetExpression (IDesignerSerializationManager manager, object instance, CodeExpression expression)
185                 {
186                         SetExpression (manager, instance, expression, false);
187                 }
188
189                 // XXX: isPreset - what does this do when set?
190                 //
191                 protected void SetExpression (IDesignerSerializationManager manager, object instance, CodeExpression expression, bool isPreset)
192                 {
193                         if (manager == null)
194                                 throw new ArgumentNullException ("manager");
195                         if (instance == null)
196                                 throw new ArgumentNullException ("instance");
197                         if (expression == null)
198                                 throw new ArgumentNullException ("expression");
199
200                         ExpressionTable expressions = manager.Context[typeof (ExpressionTable)] as ExpressionTable;
201                         if (expressions == null) {
202                                 expressions = new ExpressionTable ();
203                                 manager.Context.Append (expressions);
204                         }
205
206                         expressions[instance] = expression;
207                 }
208
209                 protected bool IsSerialized (IDesignerSerializationManager manager, object value) 
210                 {
211                         return this.IsSerialized (manager, value, false);
212                 }
213
214                 // XXX: What should honorPreset do?
215                 protected bool IsSerialized (IDesignerSerializationManager manager, object instance, bool honorPreset) 
216                 {
217                         if (instance == null)
218                                 throw new ArgumentNullException ("instance");
219                         if (manager == null)
220                                 throw new ArgumentNullException ("manager");
221
222                         if (this.GetExpression (manager, instance) != null)
223                                 return true;
224                         else
225                                 return false;
226                 }
227
228                 protected CodeExpression SerializeCreationExpression (IDesignerSerializationManager manager, object value, out bool isComplete) 
229                 {
230                         if (value == null)
231                                 throw new ArgumentNullException ("value");
232                         if (manager == null)
233                                 throw new ArgumentNullException ("manager");
234
235                         CodeExpression expression = null;
236
237                         TypeConverter converter = TypeDescriptor.GetConverter (value);
238                         if (converter != null && converter.CanConvertTo (typeof (InstanceDescriptor))) {
239                                 InstanceDescriptor descriptor = converter.ConvertTo (value, typeof (InstanceDescriptor)) as InstanceDescriptor;
240                                 isComplete = descriptor.IsComplete;
241                                 if (descriptor != null || descriptor.MemberInfo != null)
242                                         expression = this.SerializeInstanceDescriptor (manager, descriptor);
243                                 else
244                                         ReportError (manager, "Unable to serialize to InstanceDescriptor", 
245                                                                  "Value Type: " + value.GetType ().Name + System.Environment.NewLine + 
246                                                                  "Value (ToString): " + value.ToString ());
247                         } else {
248                                 expression = new CodeObjectCreateExpression (value.GetType ().FullName, new CodeExpression[0]);
249                                 isComplete = false;
250                         }
251                         return expression;
252                 }
253
254                 private CodeExpression SerializeInstanceDescriptor (IDesignerSerializationManager manager, InstanceDescriptor descriptor)
255                 {
256                         CodeExpression expression = null;
257                         MemberInfo member = descriptor.MemberInfo;
258                         CodeExpression target = new CodeTypeReferenceExpression (member.DeclaringType);
259
260                         if (member is PropertyInfo) {
261                                 expression = new CodePropertyReferenceExpression (target, member.Name);
262                         } else if (member is FieldInfo) {
263                                 expression = new CodeFieldReferenceExpression (target, member.Name);
264                         } else if (member is MethodInfo) {
265                                 CodeMethodInvokeExpression methodInvoke = new CodeMethodInvokeExpression (target, member.Name);
266                                 manager.Context.Push (new ExpressionContext (methodInvoke, methodInvoke.GetType (), null, null));
267                                 if (descriptor.Arguments != null && descriptor.Arguments.Count > 0)
268                                         methodInvoke.Parameters.AddRange (SerializeParameters (manager, descriptor.Arguments));
269                                 manager.Context.Pop ();
270                                 expression = methodInvoke;
271                         } else if (member is ConstructorInfo) {
272                                 CodeObjectCreateExpression createExpr = new CodeObjectCreateExpression (member.DeclaringType);
273                                 manager.Context.Push (new ExpressionContext (createExpr, createExpr.GetType (), null, null));
274                                 if (descriptor.Arguments != null && descriptor.Arguments.Count > 0)
275                                         createExpr.Parameters.AddRange (SerializeParameters (manager, descriptor.Arguments));
276                                 manager.Context.Pop ();
277                                 expression = createExpr;
278                         }
279
280                         return expression;
281                 }
282
283                 private CodeExpression[] SerializeParameters (IDesignerSerializationManager manager, ICollection parameters)
284                 {
285                         CodeExpression[] expressions = null;
286
287                         if (parameters != null && parameters.Count > 0) {
288                                 expressions = new CodeExpression[parameters.Count];
289                                 int i = 0;
290                                 foreach (object parameter in parameters) {
291                                         expressions[i] = this.SerializeToExpression (manager, parameter);
292                                         i++;
293                                 }
294                         }
295
296                         return expressions;
297                 }
298
299                 protected void SerializeEvent (IDesignerSerializationManager manager, CodeStatementCollection statements, 
300                                                                            object value, EventDescriptor descriptor) 
301                 {
302                         if (descriptor == null)
303                                 throw new ArgumentNullException ("descriptor");
304                         if (value == null)
305                                 throw new ArgumentNullException ("value");
306                         if (statements == null)
307                                 throw new ArgumentNullException ("statements");
308                         if (manager == null)
309                                 throw new ArgumentNullException ("manager");
310
311                         MemberCodeDomSerializer serializer = manager.GetSerializer (descriptor.GetType (), typeof (MemberCodeDomSerializer)) as MemberCodeDomSerializer;
312                         if (serializer != null && serializer.ShouldSerialize (manager, value, descriptor))
313                                 serializer.Serialize (manager, value, descriptor, statements);
314                 }
315
316                 protected void SerializeEvents (IDesignerSerializationManager manager, CodeStatementCollection statements, 
317                                                                                 object value, params Attribute[] filter)
318                 {
319                         if (filter == null)
320                                 throw new ArgumentNullException ("filter");
321                         if (value == null)
322                                 throw new ArgumentNullException ("value");
323                         if (statements == null)
324                                 throw new ArgumentNullException ("statements");
325                         if (manager == null)
326                                 throw new ArgumentNullException ("manager");
327
328                         EventDescriptorCollection events = TypeDescriptor.GetEvents (value, filter);
329                         foreach (EventDescriptor e in events) 
330                                 this.SerializeEvent (manager, statements, value, e);
331                 }
332
333                 protected void SerializeProperty (IDesignerSerializationManager manager, CodeStatementCollection statements, object value, PropertyDescriptor propertyToSerialize)
334                 {
335                         if (propertyToSerialize == null)
336                                 throw new ArgumentNullException ("propertyToSerialize");
337                         if (value == null)
338                                 throw new ArgumentNullException ("value");
339                         if (statements == null)
340                                 throw new ArgumentNullException ("statements");
341                         if (manager == null)
342                                 throw new ArgumentNullException ("manager");
343
344                         MemberCodeDomSerializer serializer = manager.GetSerializer (propertyToSerialize.GetType (), typeof (MemberCodeDomSerializer)) as MemberCodeDomSerializer;
345                         if (serializer != null && serializer.ShouldSerialize (manager, value, propertyToSerialize))
346                                 serializer.Serialize (manager, value, propertyToSerialize, statements);
347                 }
348                 
349                 protected void SerializeProperties (IDesignerSerializationManager manager, CodeStatementCollection statements, 
350                                                                                         object value, Attribute[] filter) 
351                 {
352                         if (filter == null)
353                                 throw new ArgumentNullException ("filter");
354                         if (value == null)
355                                 throw new ArgumentNullException ("value");
356                         if (statements == null)
357                                 throw new ArgumentNullException ("statements");
358                         if (manager == null)
359                                 throw new ArgumentNullException ("manager");
360
361                         PropertyDescriptorCollection properties = TypeDescriptor.GetProperties (value, filter);
362                         foreach (PropertyDescriptor property in properties)
363                                 this.SerializeProperty (manager, statements, value, property);
364                 }
365
366                 protected virtual object DeserializeInstance (IDesignerSerializationManager manager, Type type, 
367                                                                                                           object[] parameters, string name, bool addToContainer)
368                 {
369                         if (type == null)
370                                 throw new ArgumentNullException ("type");
371                         if (manager == null)
372                                 throw new ArgumentNullException ("manager");
373
374                         return manager.CreateInstance (type, parameters, name, addToContainer);
375                 }
376
377                 protected string GetUniqueName (IDesignerSerializationManager manager, object instance)
378                 {
379                         if (instance == null)
380                                 throw new ArgumentNullException ("instance");
381                         if (manager == null)
382                                 throw new ArgumentNullException ("manager");
383
384                         string name = manager.GetName (instance);
385                         if (name == null) {
386                                 INameCreationService service = manager.GetService (typeof (INameCreationService)) as INameCreationService;
387                                 name = service.CreateName (null, instance.GetType ());
388                                 if (name == null)
389                                         name = instance.GetType ().Name.ToLower ();
390                                 manager.SetName (instance, name);
391                         }
392                         return name;
393                 }
394
395                 protected object DeserializeExpression (IDesignerSerializationManager manager, string name, CodeExpression expression) 
396                 {
397                         if (expression == null)
398                                 throw new ArgumentNullException ("expression");
399                         if (manager == null)
400                                 throw new ArgumentNullException ("manager");
401
402                         object deserialized = null;
403
404                         // CodeThisReferenceExpression
405                         //
406                         CodeThisReferenceExpression thisExpr = expression as CodeThisReferenceExpression;
407                         if (thisExpr != null) {
408                                 RootContext context = manager.Context[typeof (RootContext)] as RootContext;
409                                 if (context != null) {
410                                         deserialized = context.Value;
411                                 } else {
412                                         IDesignerHost host = manager.GetService (typeof (IDesignerHost)) as IDesignerHost;
413                                         if (host != null)
414                                                 deserialized = host.RootComponent;
415                                 }
416                         }
417                         
418                         // CodeVariableReferenceExpression
419                         //
420                         CodeVariableReferenceExpression varRef = expression as CodeVariableReferenceExpression;
421                         if (deserialized == null && varRef != null) {
422                                 deserialized = manager.GetInstance (varRef.VariableName);
423                                 if (deserialized == null)
424                                         _deserializationError = "Cannot find the value of the variable " + varRef.VariableName + "";
425                         }
426
427                         // CodeFieldReferenceExpression
428                         //
429                         CodeFieldReferenceExpression fieldRef = expression as CodeFieldReferenceExpression;
430                         if (deserialized == null && fieldRef != null) {
431                                 deserialized = manager.GetInstance (fieldRef.FieldName);
432                                 if (deserialized == null)
433                                         _deserializationError = "Cannot find the value of the field " + fieldRef.FieldName + "";
434                         }
435                                 
436
437                         // CodePrimitiveExpression
438                         //
439                         CodePrimitiveExpression primitiveExp = expression as CodePrimitiveExpression;
440                         if (deserialized == null && primitiveExp != null)
441                                 deserialized = primitiveExp.Value;
442
443                         // CodePropertyReferenceExpression
444                         //
445                         CodePropertyReferenceExpression propRef = expression as CodePropertyReferenceExpression;
446                         if (deserialized == null && propRef != null) {
447                                 object target = DeserializeExpression (manager, null, propRef.TargetObject);
448                                 if (target != null) {
449                                         bool found = false;
450                                         if (target is Type) {
451                                                 PropertyInfo property = ((Type)target).GetProperty (propRef.PropertyName,
452                                                                                                                                                         BindingFlags.GetProperty | 
453                                                                                                                                                         BindingFlags.Public | BindingFlags.Static);
454                                                 if (property != null) {
455                                                         deserialized = property.GetValue (null, null);
456                                                         found = true;
457                                                 }
458
459                                                 // NRefactory seems to produce PropertyReferences to reference some fields and enums
460                                                 //
461                                                 FieldInfo field = ((Type)target).GetField (propRef.PropertyName,
462                                                                                                                                    BindingFlags.GetField | BindingFlags.Public | BindingFlags.Static);
463                                                 if (field != null) {
464                                                         deserialized = field.GetValue (null);
465                                                         found = true;
466                                                 }
467                                         } else {
468                                                 PropertyDescriptor property = TypeDescriptor.GetProperties (target)[propRef.PropertyName];
469                                                 if (property != null) {
470                                                         deserialized = property.GetValue (target);
471                                                         found = true;
472                                                 }
473
474                                                 FieldInfo field = target.GetType().GetField (propRef.PropertyName,
475                                                                                                                                    BindingFlags.GetField | BindingFlags.Public | BindingFlags.Instance);
476                                                 if (field != null) {
477                                                         deserialized = field.GetValue (null);
478                                                         found = true;
479                                                 }
480                                         }
481                                         
482                                         if (!found) {
483                                                 _deserializationError = "No property " + propRef.PropertyName + " found in type " + 
484                                                         (target is Type ? ((Type)target).Name : target.GetType ().Name);
485                                                 _deserializationErrorTrace = "Property Name: " + propRef.PropertyName + System.Environment.NewLine +
486                                                         "Property is: " + (target is Type ? "static" : "instance") + System.Environment.NewLine +
487                                                         "Property Holder Type: " + (target is Type ? ((Type)target).Name : target.GetType ().Name) + System.Environment.NewLine +
488                                                         "Property Holder Expression Type: " + propRef.TargetObject.GetType ().Name + System.Environment.NewLine;
489                                         }
490                                 }
491                         }
492
493                         // CodeObjectCreateExpression
494                         //
495                         CodeObjectCreateExpression createExpr = expression as CodeObjectCreateExpression;
496                         if (deserialized == null && createExpr != null) {
497                                 Type type = manager.GetType (createExpr.CreateType.BaseType);
498                                 if (type == null) {
499                                         _deserializationError = "Unable to find the type " + createExpr.CreateType.BaseType;
500                                 } else {
501                                         object[] arguments = new object[createExpr.Parameters.Count];
502                                         for (int i=0; i < createExpr.Parameters.Count; i++) {
503                                                 arguments[i] = this.DeserializeExpression (manager, null, createExpr.Parameters[i]);
504                                                 if (_deserializationError != null) {
505                                                         _deserializationErrorTrace = "Type to create: " + createExpr.CreateType.BaseType + System.Environment.NewLine +
506                                                                 "Parameter Number: " + i.ToString () + System.Environment.NewLine +
507                                                                 "Parameter Expression Type: " + createExpr.Parameters[i].GetType ().Name + System.Environment.NewLine +
508                                                                 "Parameters Count: " + createExpr.Parameters.Count + System.Environment.NewLine + 
509                                                                 _deserializationErrorTrace;
510                                                         break;
511                                                 }
512                                         }
513                                         if (_deserializationError == null) {
514                                                 bool addToContainer = false;
515                                                 if (typeof(IComponent).IsAssignableFrom (type))
516                                                         addToContainer = true;
517                                                 deserialized = this.DeserializeInstance (manager, type, arguments, name, addToContainer);
518                                                 if (deserialized == null) {
519                                                         _deserializationError = "Unable to create an instance of type " + createExpr.CreateType.BaseType;
520                                                         _deserializationErrorTrace = "Type to create: " + createExpr.CreateType.BaseType + System.Environment.NewLine +
521                                                                 "Name: " + name + System.Environment.NewLine +
522                                                                 "addToContainer: " + addToContainer.ToString () + System.Environment.NewLine +
523                                                                 "Parameters Count: " + createExpr.Parameters.Count + System.Environment.NewLine;
524         
525                                                         for (int i=0; i < arguments.Length; i++) {
526                                                                 _deserializationErrorTrace += "Parameter Number: " + i.ToString () + System.Environment.NewLine +
527                                                                         "Parameter Type: " + (arguments[i] == null ? "null" : arguments[i].GetType ().Name) +
528                                                                         System.Environment.NewLine +
529                                                                         "Parameter " + i.ToString () + " Value: " + arguments[i].ToString () + System.Environment.NewLine;
530                                                         }
531                                                 }
532                                         }
533                                 }
534                         }
535
536                         // CodeArrayCreateExpression
537                         //
538                         CodeArrayCreateExpression arrayCreateExpr = expression as CodeArrayCreateExpression;
539                         if (deserialized == null && arrayCreateExpr != null) {
540                                 Type arrayType = manager.GetType (arrayCreateExpr.CreateType.BaseType);
541                                 if (arrayType == null) {
542                                         _deserializationError = "Unable to find the type " + arrayCreateExpr.CreateType.BaseType;
543                                 } else {
544                                         ArrayList initializers = new ArrayList ();
545                                         Type elementType = arrayType.GetElementType ();
546                                         deserialized = Array.CreateInstance (arrayType, arrayCreateExpr.Initializers.Count);
547                                         for (int i = 0; i < arrayCreateExpr.Initializers.Count; i++) {
548                                                 object element = this.DeserializeExpression (manager, null, arrayCreateExpr.Initializers[i]);
549                                                 if (_deserializationError != null) {
550                                                         _deserializationErrorTrace = "Array Type: " + arrayType.Name + System.Environment.NewLine +
551                                                                 "Array Element Type: " + elementType + System.Environment.NewLine +
552                                                                 "Initializer Number: " + i.ToString () + System.Environment.NewLine +
553                                                                 "Initializer Type: " + (element == null ? "null" : element.GetType ().Name) + System.Environment.NewLine +
554                                                                 "Initialzer Value" + (element == null ? "null" : element.ToString ()) + System.Environment.NewLine +
555                                                                 _deserializationErrorTrace;
556                                                 } else {
557                                                         if (arrayType.IsInstanceOfType (element)) {
558                                                                 initializers.Add (element);
559                                                         } else {
560                                                                 _deserializationError = "Array initializer of incompatible type detected.";
561                                                                 _deserializationErrorTrace = "Array Type: " + arrayType.Name + System.Environment.NewLine +
562                                                                         "Array Element Type: " + elementType + System.Environment.NewLine +
563                                                                         "Initializer Type: " + (element == null ? "null" : element.GetType ().Name) + System.Environment.NewLine;
564                                                         }
565                                                 }
566                                         }
567                                         if (_deserializationError == null)
568                                                 initializers.CopyTo ((Array)deserialized, 0);
569                                         else
570                                                 deserialized = null;
571                                 }
572                         }
573
574                         // CodeMethodInvokeExpression
575                         //
576                         CodeMethodInvokeExpression methodExpr = expression as CodeMethodInvokeExpression;
577                         if (deserialized == null && methodExpr != null) {
578                                 object target = this.DeserializeExpression (manager, null, methodExpr.Method.TargetObject);
579                                 object[] parameters = new object[methodExpr.Parameters.Count];
580                                 for (int i=0; i < methodExpr.Parameters.Count; i++) {
581                                         parameters[i] = this.DeserializeExpression (manager, null, methodExpr.Parameters[i]);
582                                         if (_deserializationError != null) {
583                                                 _deserializationErrorTrace =
584                                                         "Parameter Number: " + i.ToString () + System.Environment.NewLine +
585                                                         "Parameter Expression Type: " + methodExpr.Parameters[i].GetType ().Name + System.Environment.NewLine +
586                                                         _deserializationErrorTrace;
587                                                 break;
588                                         }
589                                 }
590
591                                 if (_deserializationError == null) {
592                                         MethodInfo method = null;
593                                         if (target is Type) {
594                                                 method = GetExactMethod ((Type)target, methodExpr.Method.MethodName, 
595                                                                                                  BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static,
596                                                                                                  parameters);
597                                         } else {
598                                                 method = GetExactMethod (target.GetType(), methodExpr.Method.MethodName, 
599                                                                                                  BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Instance,
600                                                                                                  parameters);
601                                         }
602         
603                                         if (method != null) {
604                                                 deserialized = method.Invoke (target, parameters);
605                                         } else {
606                                                 _deserializationError = "Unable to find a matching method " + methodExpr.Method.MethodName + " in type " +
607                                                         (target is Type ? ((Type)target).Name : target.GetType ().Name);
608                                                 for (int i = 0; i < parameters.Length; i++) {
609                                                         _deserializationErrorTrace += "Parameter Number: " + i.ToString () + System.Environment.NewLine +
610                                                                 "Parameter Type: " + (parameters[i] == null ? "null" : parameters[i].GetType ().Name) +
611                                                                 System.Environment.NewLine +
612                                                                 "Parameter " + i.ToString () + " Value: " + parameters[i].ToString () + System.Environment.NewLine;
613                                                 }
614                                         }
615         
616                                         if (_deserializationError != null) {
617                                                 _deserializationErrorTrace = 
618                                                         "Method Name: " + methodExpr.Method.MethodName + System.Environment.NewLine +
619                                                         "Method is: " + (target is Type ? "static" : "instance") + System.Environment.NewLine +
620                                                         "Method Holder Type: " + (target is Type ? ((Type)target).Name : target.GetType ().Name) + System.Environment.NewLine +
621                                                         "Parameters Count: " + methodExpr.Parameters.Count + System.Environment.NewLine +
622                                                         _deserializationErrorTrace;
623                                         }
624                                 }
625                         }
626
627                         // CodeTypeReferenceExpression
628                         //
629                         CodeTypeReferenceExpression typeRef = expression as CodeTypeReferenceExpression;
630                         if (deserialized == null && typeRef != null) {
631                                 deserialized = manager.GetType (typeRef.Type.BaseType);
632                                 if (deserialized == null)
633                                         _deserializationError = "Unable to find the type " + typeRef.Type.BaseType;
634                         }
635
636                         // CodeCastExpression
637                         // 
638                         CodeCastExpression castExpr = expression as CodeCastExpression;
639                         if (deserialized == null && castExpr != null) {
640                                 Type targetType = manager.GetType (castExpr.TargetType.BaseType);
641                                 if (targetType == null)
642                                         _deserializationError = "Unable to find the type " + castExpr.TargetType.BaseType;
643
644                                 object instance = DeserializeExpression (manager, null, castExpr.Expression);
645                                 if (instance != null && targetType != null) {
646                                         IConvertible convertible = instance as IConvertible;
647                                         if (convertible != null) {
648                                                 try {
649                                                         instance = convertible.ToType (targetType, null);
650                                                 } catch {
651                                                         _deserializationError = "Unable to convert type " + instance.GetType ().Name + 
652                                                                 " to type " + castExpr.TargetType.BaseType;
653                                                 }
654                                         } else {
655                                                 _deserializationError = "Unable to convert type " + instance.GetType ().Name + 
656                                                         " to type " + castExpr.TargetType.BaseType;
657                                         }
658
659                                         deserialized = instance;
660                                 }
661                                 if (_deserializationError != null) {
662                                         _deserializationErrorTrace = "Target Type: " + castExpr.TargetType.BaseType + System.Environment.NewLine +
663                                                 "Instance Type: " + (instance == null ? "null" : instance.GetType ().Name) + System.Environment.NewLine +
664                                                 "Instance Value: " + (instance == null ? "null" : instance.ToString()) + System.Environment.NewLine +
665                                                 "Instance is IConvertible: " + (instance is IConvertible).ToString() + System.Environment.NewLine +
666                                                 _deserializationErrorTrace;
667                                 }
668                         }
669
670
671                         // CodeBinaryOperatorExpression
672                         //
673                         CodeBinaryOperatorExpression binOperator = expression as CodeBinaryOperatorExpression;
674                         if (deserialized == null && binOperator != null) {
675                                 IConvertible left = null;
676                                 IConvertible right = null;
677                                 switch (binOperator.Operator) {
678                                         case CodeBinaryOperatorType.BitwiseOr:
679                                                 left = DeserializeExpression (manager, null, binOperator.Left) as IConvertible;
680                                                 right = DeserializeExpression (manager, null, binOperator.Right) as IConvertible;
681                                                 if (left is Enum && right is Enum) 
682                                                         deserialized = Enum.ToObject (left.GetType (), Convert.ToInt64 (left) | Convert.ToInt64 (right));
683                                                 else
684                                                         _deserializationError = "CodeBinaryOperatorType.BitwiseOr only supported for Enum types";
685                                                 break;
686                                         default:
687                                                 _deserializationError = "Unsupported CodeBinaryOperatorType: " + binOperator.Operator.ToString ();
688                                                 break;
689                                 }
690
691                                 if (_deserializationError != null) {
692                                         _deserializationErrorTrace = "BinaryOperator Type: " + binOperator.Operator.ToString() + System.Environment.NewLine +
693                                                 "Left Type: " + (left == null ? "null" : left.GetType().Name) + System.Environment.NewLine +
694                                                 "Left Value: " + (left == null ? "null" : left.ToString ()) + System.Environment.NewLine +
695                                                 "Left Expression Type: " + binOperator.Left.GetType ().Name + System.Environment.NewLine +
696                                                 "Right Type: " + (right == null ? "null" : right.GetType().Name) + System.Environment.NewLine +
697                                                 "Right Value: " + (right == null ? "null" : right.ToString ()) + System.Environment.NewLine +
698                                                 "Right Expression Type: " + binOperator.Right.GetType ().Name + System.Environment.NewLine +
699                                                 _deserializationErrorTrace;
700                                 }
701                         }
702
703
704                         if (_deserializationError != null) {
705                                 _deserializationErrorTrace = "* DeserializeExpression (" + expression.GetType().Name + ")" 
706                                         + System.Environment.NewLine + _deserializationErrorTrace;
707                         } else {
708                                 if (deserialized == null && !(expression is CodePrimitiveExpression) && !(expression is CodeMethodInvokeExpression))
709                                         _deserializationError = "Unsupported Expression Type: " + expression.GetType ().Name;
710                         }
711
712                         return deserialized;
713                 }
714
715                 // Searches for a method on type that matches argument types
716                 //
717                 private MethodInfo GetExactMethod (Type type, string methodName, BindingFlags flags, ICollection argsCollection)
718                 {
719                         object[] arguments = null;
720                         Type[] types = new Type[0];
721
722                         if (argsCollection != null) {
723                                 arguments = new object[argsCollection.Count];
724                                 types = new Type[argsCollection.Count];
725                                 argsCollection.CopyTo (arguments, 0);
726
727                                 for (int i=0; i < arguments.Length; i++) {
728                                         if (arguments[i] == null)
729                                                 types[i] = null;
730                                         else
731                                                 types[i] = arguments[i].GetType ();
732                                 }
733                         }
734
735                         return type.GetMethod (methodName, flags, null, types, null);
736                 }
737
738                 protected void DeserializeStatement (IDesignerSerializationManager manager, CodeStatement statement)
739                 {
740                         if (statement == null)
741                                 throw new ArgumentNullException ("statement");
742                         if (manager == null)
743                                 throw new ArgumentNullException ("manager");
744
745                         _deserializationErrorTrace = null;
746                         _deserializationError = null;
747
748                         // CodeAssignStatement
749                         //
750                         CodeAssignStatement assignment = statement as CodeAssignStatement;
751                         if (assignment != null)
752                                 DeserializeAssignmentStatement (manager, assignment);
753
754                         // CodeExpressionStatement
755                         //
756                         CodeExpressionStatement expression = statement as CodeExpressionStatement;
757                         if (expression != null)
758                                 this.DeserializeExpression (manager, null, expression.Expression);
759
760                         // CodeAttachEventStatement
761                         //
762                         CodeAttachEventStatement attachStatement = statement as CodeAttachEventStatement;
763                         if (attachStatement != null) {
764                                 string methodName = null;
765
766                                 CodeObjectCreateExpression createExpr = attachStatement.Listener as CodeObjectCreateExpression;
767                                 if (createExpr != null && createExpr.Parameters.Count == 1 ) { // += new EventType (method)
768                                         CodeMethodReferenceExpression handlerRef = createExpr.Parameters[0] as CodeMethodReferenceExpression;
769                                         if (handlerRef != null)
770                                                 methodName = handlerRef.MethodName;
771                                 }
772
773                                 CodeDelegateCreateExpression delegateCreateExpr = attachStatement.Listener as CodeDelegateCreateExpression;
774                                 if (delegateCreateExpr != null)// += new EventType (method)
775                                         methodName = delegateCreateExpr.MethodName;
776
777                                 CodeMethodReferenceExpression methodRef = attachStatement.Listener as CodeMethodReferenceExpression;
778                                 if (methodRef != null) // += method
779                                         methodName = methodRef.MethodName;
780
781                                 object component = DeserializeExpression (manager, null, attachStatement.Event.TargetObject);
782                                 if (component != null && methodName != null) {
783                                         EventDescriptor eventDescriptor = TypeDescriptor.GetEvents (component)[attachStatement.Event.EventName];
784                                         if (eventDescriptor != null) {
785                                                 IEventBindingService service = manager.GetService (typeof (IEventBindingService)) as IEventBindingService;
786                                                 if (service != null)
787                                                         service.GetEventProperty (eventDescriptor).SetValue (component, methodName);
788                                                 else
789                                                         _deserializationError = "IEventBindingService missing.";
790                                         } else {
791                                                 _deserializationError = "No event " + attachStatement.Event.EventName + 
792                                                         " found in type " + component.GetType ().Name;
793                                         }
794                                 }
795
796                                 if (_deserializationError != null) {
797                                         _deserializationErrorTrace = "Method Name: " + methodName + System.Environment.NewLine +
798                                                 "Event Name: " + attachStatement.Event.EventName + System.Environment.NewLine +
799                                                 "Listener Expression Type: " + methodRef.GetType ().Name + System.Environment.NewLine +
800                                                 "Event Holder Type: " + component.GetType ().Name + System.Environment.NewLine +
801                                                 "Event Holder Expression Type: " + attachStatement.Event.TargetObject.GetType ().Name + System.Environment.NewLine;
802                                 }
803                         }
804
805                         if (_deserializationErrorTrace != null) {
806                                 _deserializationErrorTrace = "* DeserializeStatement (" + statement.GetType().Name + ")" 
807                                         + System.Environment.NewLine + _deserializationErrorTrace;
808                                 ReportError (manager, _deserializationError, _deserializationErrorTrace);
809                                 _deserializationErrorTrace = null;
810                                 _deserializationError = null;
811                         }
812                 }
813
814                 private void DeserializeAssignmentStatement (IDesignerSerializationManager manager, CodeAssignStatement statement)
815                 {
816                         CodeExpression leftExpr = statement.Left;
817                         
818                         // Assign to a Property
819                         //
820                         CodePropertyReferenceExpression propRef = leftExpr as CodePropertyReferenceExpression;
821                         if (propRef != null) {
822                                 object propertyHolder = DeserializeExpression (manager, null, propRef.TargetObject);
823                                 object value = null;
824                                 if (_deserializationError == null)
825                                         value = DeserializeExpression (manager, null, statement.Right);
826
827                                 if (_deserializationError == null && propertyHolder != null) {
828                                         PropertyDescriptor property = TypeDescriptor.GetProperties (propertyHolder)[propRef.PropertyName];
829                                         if (property != null) {
830                                                 property.SetValue (propertyHolder, value);
831                                         } else {
832                                                 _deserializationError = "No property " + propRef.PropertyName + " found in type " + propertyHolder.GetType ().Name;
833                                                 _deserializationErrorTrace = "Property Name: " + propRef.PropertyName + System.Environment.NewLine +
834                                                         "Property Value: " + (value == null ? "null" : value.ToString()) + System.Environment.NewLine +
835                                                         "Property Type: " + propertyHolder.GetType ().Name + System.Environment.NewLine +
836                                                         "Property Holder Expression Type: " + propRef.TargetObject.GetType ().Name + System.Environment.NewLine;
837                                         }
838                                 }
839                         }
840                         
841                         // Assign to a Field
842                         // 
843                         CodeFieldReferenceExpression fieldRef = leftExpr as CodeFieldReferenceExpression;
844                         if (fieldRef != null && fieldRef.FieldName != null) {
845                                 // Note that if the Right expression is a CodeCreationExpression the component will be created in this call
846                                 //
847                                 object fieldHolder = DeserializeExpression (manager, null, fieldRef.TargetObject);
848                                 object value = null;
849                                 if (_deserializationError == null)
850                                         value = DeserializeExpression (manager, fieldRef.FieldName, statement.Right);
851                                 FieldInfo field = null;
852
853                                 RootContext context = manager.Context[typeof (RootContext)] as RootContext;
854                                 if (_deserializationError == null && fieldHolder != null) {
855                                         if (fieldRef.TargetObject is CodeThisReferenceExpression && context != null && context.Value == fieldHolder) {
856                                                 // Do not deserialize the fields of the root component, because the root component type 
857                                                 // is actually an instance of the its parent type, e.g: CustomControl : _UserControl_
858                                                 // and thus it doesn't contain the fields. The trick is that once DeserializeExpression 
859                                                 // is called on a CodeObjectCreateExpression the component is created and is added to the name-instance
860                                                 // table.
861                                                 // 
862                                         } else {
863                                                 if (fieldHolder is Type) // static field
864                                                         field = ((Type)fieldHolder).GetField (fieldRef.FieldName, 
865                                                                                                                                         BindingFlags.GetField | BindingFlags.Public | BindingFlags.Static);
866                                                 else // instance field
867                                                         field = fieldHolder.GetType().GetField (fieldRef.FieldName, 
868                                                                                                                                         BindingFlags.GetField | BindingFlags.Public | BindingFlags.Instance);
869                                                 if (field != null)
870                                                         field.SetValue (fieldHolder, value);
871                                                 else {
872                                                         _deserializationError = "No field " + fieldRef.FieldName + " found in type " + fieldHolder.GetType ().Name;
873                                                         _deserializationErrorTrace = "Field Name: " + fieldRef.FieldName + System.Environment.NewLine +
874                                                                 "Field is: " + (fieldHolder is Type ? "static" : "instance") + System.Environment.NewLine +
875                                                                 "Field Value: " + (value == null ? "null" : value.ToString()) + System.Environment.NewLine +
876                                                                 "Field Holder Type: " + fieldHolder.GetType ().Name + System.Environment.NewLine +
877                                                                 "Field Holder Expression Type: " + fieldRef.TargetObject.GetType ().Name + System.Environment.NewLine;
878                                                 }
879                                         }
880                                 }
881                         }
882
883                         if (_deserializationError != null) {
884                                 _deserializationErrorTrace = "* DeserializeAssignStatement" + System.Environment.NewLine + 
885                                         "Left Expression Type: " + statement.Left.GetType().Name + System.Environment.NewLine +
886                                         "Right Expression Type: " + statement.Right.GetType().Name + System.Environment.NewLine +
887                                         _deserializationErrorTrace;
888                         }
889                 }
890
891                 internal void ReportError (IDesignerSerializationManager manager, string message)
892                 {
893                         this.ReportError (manager, message, "");
894                 }
895
896                 internal void ReportError (IDesignerSerializationManager manager, string message, string details)
897                 {
898                         try {
899                                 throw new Exception (message);
900                         } catch (Exception e) {
901                                 e.Data["Details"] = message + Environment.NewLine + Environment.NewLine + details;
902                                 manager.ReportError (e);
903                         }
904                 }
905
906 #region Resource Serialization - TODO
907                 protected CodeExpression SerializeToResourceExpression (IDesignerSerializationManager manager, object value) 
908                 {
909                         throw new NotImplementedException ();
910                 }
911                 
912                 protected CodeExpression SerializeToResourceExpression (IDesignerSerializationManager manager, object value, bool ensureInvariant) 
913                 {
914                         throw new NotImplementedException ();
915                 }
916                 
917                 protected void SerializePropertiesToResources (IDesignerSerializationManager manager, CodeStatementCollection statements, 
918                                                                                                            object value, Attribute[] filter) 
919                 {
920                         throw new NotImplementedException ();
921                 }
922
923                 protected void SerializeResource (IDesignerSerializationManager manager, string resourceName, object value)
924                 {
925                         throw new NotImplementedException ();
926                 }
927
928                 protected void SerializeResourceInvariant (IDesignerSerializationManager manager, string resourceName, object value) 
929                 {
930                         throw new NotImplementedException ();
931                 }
932
933                 protected void DeserializePropertiesFromResources (IDesignerSerializationManager manager, object value, Attribute[] filter)
934                 {
935                         throw new NotImplementedException ();
936                 }
937 #endregion
938         }
939 }
940 #endif