2 // System.ComponentModel.Design.Serialization.CodeDomSerializerBase
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
.Reflection
;
35 using System
.ComponentModel
;
36 using System
.ComponentModel
.Design
;
40 namespace System
.ComponentModel
.Design
.Serialization
42 [EditorBrowsable (EditorBrowsableState
.Never
)]
43 public abstract class CodeDomSerializerBase
46 // MSDN says that if the deserialization fails a CodeExpression is returned
48 private sealed class DeserializationErrorMarker
: CodeExpression
50 public override bool Equals (object o
)
55 public override int GetHashCode ()
57 return base.GetHashCode ();
61 private static readonly DeserializationErrorMarker _errorMarker
= new DeserializationErrorMarker ();
63 internal CodeDomSerializerBase ()
67 private class ExpressionTable
: Hashtable
// just so that we have a specific type to append to the context stack
71 protected CodeExpression
SerializeToExpression (IDesignerSerializationManager manager
, object instance
)
74 throw new ArgumentNullException ("manager");
76 CodeExpression expression
= null;
78 expression
= this.GetExpression (manager
, instance
); // 1 - IDesignerSerializationManager.GetExpression
79 if (expression
== null) {
80 CodeDomSerializer serializer
= this.GetSerializer (manager
, instance
); // 2 - manager.GetSerializer().Serialize()
81 if (serializer
!= null) {
82 object serialized
= serializer
.Serialize (manager
, instance
);
83 expression
= serialized
as CodeExpression
; // 3 - CodeStatement or CodeStatementCollection
84 if (expression
== null) {
85 CodeStatement statement
= serialized
as CodeStatement
;
86 CodeStatementCollection statements
= serialized
as CodeStatementCollection
;
88 if (statement
!= null || statements
!= null) {
89 CodeStatementCollection contextStatements
= null;
91 StatementContext context
= manager
.Context
[typeof (StatementContext
)] as StatementContext
;
92 if (context
!= null && instance
!= null)
93 contextStatements
= context
.StatementCollection
[instance
];
95 if (contextStatements
== null)
96 contextStatements
= manager
.Context
[typeof (CodeStatementCollection
)] as CodeStatementCollection
;
98 if (contextStatements
!= null) {
99 if (statements
!= null)
100 contextStatements
.AddRange (statements
);
102 contextStatements
.Add (statement
);
106 if (expression
== null && instance
!= null)
107 expression
= this.GetExpression (manager
, instance
); // 4
109 ReportError (manager
, "No serializer found for type '" + instance
.GetType ().Name
+ "'");
115 protected CodeDomSerializer
GetSerializer (IDesignerSerializationManager manager
, object instance
)
117 DesignerSerializerAttribute attrInstance
, attrType
;
118 attrType
= attrInstance
= null;
120 CodeDomSerializer serializer
= null;
121 if (instance
== null)
122 serializer
= this.GetSerializer (manager
, null);
124 AttributeCollection attributes
= TypeDescriptor
.GetAttributes (instance
);
125 foreach (Attribute a
in attributes
) {
126 DesignerSerializerAttribute designerAttr
= a
as DesignerSerializerAttribute
;
127 if (designerAttr
!= null && manager
.GetType (designerAttr
.SerializerBaseTypeName
) == typeof (CodeDomSerializer
)) {
128 attrInstance
= designerAttr
;
133 attributes
= TypeDescriptor
.GetAttributes (instance
.GetType ());
134 foreach (Attribute a
in attributes
) {
135 DesignerSerializerAttribute designerAttr
= a
as DesignerSerializerAttribute
;
136 if (designerAttr
!= null && manager
.GetType (designerAttr
.SerializerBaseTypeName
) == typeof (CodeDomSerializer
)) {
137 attrType
= designerAttr
;
142 // if there is metadata modification in the instance then create the specified serializer instead of the one
144 if (attrType
!= null && attrInstance
!= null && attrType
.SerializerTypeName
!= attrInstance
.SerializerTypeName
)
145 serializer
= Activator
.CreateInstance (manager
.GetType (attrInstance
.SerializerTypeName
)) as CodeDomSerializer
;
147 serializer
= this.GetSerializer (manager
, instance
.GetType ());
153 protected CodeDomSerializer
GetSerializer (IDesignerSerializationManager manager
, Type instanceType
)
155 return manager
.GetSerializer (instanceType
, typeof (CodeDomSerializer
)) as CodeDomSerializer
;
158 protected CodeExpression
GetExpression (IDesignerSerializationManager manager
, object instance
)
161 throw new ArgumentNullException ("manager");
162 if (instance
== null)
163 throw new ArgumentNullException ("instance");
165 CodeExpression expression
= null;
167 ExpressionTable expressions
= manager
.Context
[typeof (ExpressionTable
)] as ExpressionTable
;
168 if (expressions
!= null) // 1st try: ExpressionTable
169 expression
= expressions
[instance
] as CodeExpression
;
171 if (expression
== null) { // 2nd try: RootContext
172 RootContext context
= manager
.Context
[typeof (RootContext
)] as RootContext
;
173 if (context
!= null && context
.Value
== instance
)
174 expression
= context
.Expression
;
177 if (expression
== null) { // 3rd try: IReferenceService (instance.property.property.property
178 string name
= manager
.GetName (instance
);
179 if (name
== null || name
.IndexOf (".") == -1) {
180 IReferenceService service
= manager
.GetService (typeof (IReferenceService
)) as IReferenceService
;
181 if (service
!= null) {
182 name
= service
.GetName (instance
);
183 if (name
!= null && name
.IndexOf (".") != -1) {
184 string[] parts
= name
.Split (new char[] { ',' }
);
185 instance
= manager
.GetInstance (parts
[0]);
186 if (instance
!= null) {
187 expression
= SerializeToExpression (manager
, instance
);
188 if (expression
!= null) {
189 for (int i
=1; i
< parts
.Length
; i
++)
190 expression
= new CodePropertyReferenceExpression (expression
, parts
[i
]);
200 protected void SetExpression (IDesignerSerializationManager manager
, object instance
, CodeExpression expression
)
202 SetExpression (manager
, instance
, expression
, false);
205 // XXX: isPreset - what does this do when set?
207 protected void SetExpression (IDesignerSerializationManager manager
, object instance
, CodeExpression expression
, bool isPreset
)
210 throw new ArgumentNullException ("manager");
211 if (instance
== null)
212 throw new ArgumentNullException ("instance");
213 if (expression
== null)
214 throw new ArgumentNullException ("expression");
216 ExpressionTable expressions
= manager
.Context
[typeof (ExpressionTable
)] as ExpressionTable
;
217 if (expressions
== null) {
218 expressions
= new ExpressionTable ();
219 manager
.Context
.Append (expressions
);
222 expressions
[instance
] = expression
;
225 protected bool IsSerialized (IDesignerSerializationManager manager
, object value)
227 return this.IsSerialized (manager
, value, false);
230 // XXX: What should honorPreset do?
231 protected bool IsSerialized (IDesignerSerializationManager manager
, object instance
, bool honorPreset
)
233 if (instance
== null)
234 throw new ArgumentNullException ("instance");
236 throw new ArgumentNullException ("manager");
238 if (this.GetExpression (manager
, instance
) != null)
244 protected CodeExpression
SerializeCreationExpression (IDesignerSerializationManager manager
, object value, out bool isComplete
)
247 throw new ArgumentNullException ("value");
249 throw new ArgumentNullException ("manager");
251 CodeExpression expression
= null;
253 TypeConverter converter
= TypeDescriptor
.GetConverter (value);
254 if (converter
!= null && converter
.CanConvertTo (typeof (InstanceDescriptor
))) {
255 InstanceDescriptor descriptor
= converter
.ConvertTo (value, typeof (InstanceDescriptor
)) as InstanceDescriptor
;
256 isComplete
= descriptor
.IsComplete
;
257 if (descriptor
!= null || descriptor
.MemberInfo
!= null)
258 expression
= this.SerializeInstanceDescriptor (manager
, descriptor
);
260 ReportError (manager
, "Unable to serialize to InstanceDescriptor",
261 "Value Type: " + value.GetType ().Name
+ System
.Environment
.NewLine
+
262 "Value (ToString): " + value.ToString ());
264 if (value.GetType().GetConstructor (Type
.EmptyTypes
) != null)
265 expression
= new CodeObjectCreateExpression (value.GetType ().FullName
, new CodeExpression
[0]);
271 private CodeExpression
SerializeInstanceDescriptor (IDesignerSerializationManager manager
, InstanceDescriptor descriptor
)
273 CodeExpression expression
= null;
274 MemberInfo member
= descriptor
.MemberInfo
;
275 CodeExpression target
= new CodeTypeReferenceExpression (member
.DeclaringType
);
277 if (member
is PropertyInfo
) {
278 expression
= new CodePropertyReferenceExpression (target
, member
.Name
);
279 } else if (member
is FieldInfo
) {
280 expression
= new CodeFieldReferenceExpression (target
, member
.Name
);
281 } else if (member
is MethodInfo
) {
282 CodeMethodInvokeExpression methodInvoke
= new CodeMethodInvokeExpression (target
, member
.Name
);
283 if (descriptor
.Arguments
!= null && descriptor
.Arguments
.Count
> 0)
284 methodInvoke
.Parameters
.AddRange (SerializeParameters (manager
, descriptor
.Arguments
));
285 expression
= methodInvoke
;
286 } else if (member
is ConstructorInfo
) {
287 CodeObjectCreateExpression createExpr
= new CodeObjectCreateExpression (member
.DeclaringType
);
288 if (descriptor
.Arguments
!= null && descriptor
.Arguments
.Count
> 0)
289 createExpr
.Parameters
.AddRange (SerializeParameters (manager
, descriptor
.Arguments
));
290 expression
= createExpr
;
296 private CodeExpression
[] SerializeParameters (IDesignerSerializationManager manager
, ICollection parameters
)
298 CodeExpression
[] expressions
= null;
300 if (parameters
!= null && parameters
.Count
> 0) {
301 expressions
= new CodeExpression
[parameters
.Count
];
303 foreach (object parameter
in parameters
) {
304 expressions
[i
] = this.SerializeToExpression (manager
, parameter
);
312 protected void SerializeEvent (IDesignerSerializationManager manager
, CodeStatementCollection statements
,
313 object value, EventDescriptor descriptor
)
315 if (descriptor
== null)
316 throw new ArgumentNullException ("descriptor");
318 throw new ArgumentNullException ("value");
319 if (statements
== null)
320 throw new ArgumentNullException ("statements");
322 throw new ArgumentNullException ("manager");
324 MemberCodeDomSerializer serializer
= manager
.GetSerializer (descriptor
.GetType (), typeof (MemberCodeDomSerializer
)) as MemberCodeDomSerializer
;
325 if (serializer
!= null && serializer
.ShouldSerialize (manager
, value, descriptor
))
326 serializer
.Serialize (manager
, value, descriptor
, statements
);
329 protected void SerializeEvents (IDesignerSerializationManager manager
, CodeStatementCollection statements
,
330 object value, params Attribute
[] filter
)
333 throw new ArgumentNullException ("filter");
335 throw new ArgumentNullException ("value");
336 if (statements
== null)
337 throw new ArgumentNullException ("statements");
339 throw new ArgumentNullException ("manager");
341 EventDescriptorCollection events
= TypeDescriptor
.GetEvents (value, filter
);
342 foreach (EventDescriptor e
in events
)
343 this.SerializeEvent (manager
, statements
, value, e
);
346 protected void SerializeProperty (IDesignerSerializationManager manager
, CodeStatementCollection statements
,
347 object value, PropertyDescriptor propertyToSerialize
)
349 if (propertyToSerialize
== null)
350 throw new ArgumentNullException ("propertyToSerialize");
352 throw new ArgumentNullException ("value");
353 if (statements
== null)
354 throw new ArgumentNullException ("statements");
356 throw new ArgumentNullException ("manager");
358 MemberCodeDomSerializer serializer
= manager
.GetSerializer (propertyToSerialize
.GetType (),
359 typeof (MemberCodeDomSerializer
)) as MemberCodeDomSerializer
;
360 if (serializer
!= null && serializer
.ShouldSerialize (manager
, value, propertyToSerialize
))
361 serializer
.Serialize (manager
, value, propertyToSerialize
, statements
);
364 protected void SerializeProperties (IDesignerSerializationManager manager
, CodeStatementCollection statements
,
365 object value, Attribute
[] filter
)
368 throw new ArgumentNullException ("filter");
370 throw new ArgumentNullException ("value");
371 if (statements
== null)
372 throw new ArgumentNullException ("statements");
374 throw new ArgumentNullException ("manager");
376 PropertyDescriptorCollection properties
= TypeDescriptor
.GetProperties (value, filter
);
377 foreach (PropertyDescriptor property
in properties
) {
378 if (!property
.Attributes
.Contains (DesignerSerializationVisibilityAttribute
.Hidden
))
379 this.SerializeProperty (manager
, statements
, value, property
);
383 protected virtual object DeserializeInstance (IDesignerSerializationManager manager
, Type type
,
384 object[] parameters
, string name
, bool addToContainer
)
387 throw new ArgumentNullException ("type");
389 throw new ArgumentNullException ("manager");
391 return manager
.CreateInstance (type
, parameters
, name
, addToContainer
);
394 protected string GetUniqueName (IDesignerSerializationManager manager
, object instance
)
396 if (instance
== null)
397 throw new ArgumentNullException ("instance");
399 throw new ArgumentNullException ("manager");
401 string name
= manager
.GetName (instance
);
403 INameCreationService service
= manager
.GetService (typeof (INameCreationService
)) as INameCreationService
;
404 name
= service
.CreateName (null, instance
.GetType ());
406 name
= instance
.GetType ().Name
.ToLower ();
407 manager
.SetName (instance
, name
);
412 protected object DeserializeExpression (IDesignerSerializationManager manager
, string name
, CodeExpression expression
)
414 if (expression
== null)
415 throw new ArgumentNullException ("expression");
417 throw new ArgumentNullException ("manager");
419 bool errorOccurred
= false;
420 object deserialized
= null;
422 // CodeThisReferenceExpression
424 CodeThisReferenceExpression thisExpr
= expression
as CodeThisReferenceExpression
;
425 if (thisExpr
!= null) {
426 RootContext context
= manager
.Context
[typeof (RootContext
)] as RootContext
;
427 if (context
!= null) {
428 deserialized
= context
.Value
;
430 IDesignerHost host
= manager
.GetService (typeof (IDesignerHost
)) as IDesignerHost
;
432 deserialized
= host
.RootComponent
;
436 // CodeVariableReferenceExpression
438 CodeVariableReferenceExpression varRef
= expression
as CodeVariableReferenceExpression
;
439 if (deserialized
== null && varRef
!= null) {
440 deserialized
= manager
.GetInstance (varRef
.VariableName
);
441 if (deserialized
== null) {
442 ReportError (manager
, "Variable '" + varRef
.VariableName
+ "' not initialized prior to reference");
443 errorOccurred
= true;
447 // CodeFieldReferenceExpression (used for Enum references as well)
449 CodeFieldReferenceExpression fieldRef
= expression
as CodeFieldReferenceExpression
;
450 if (deserialized
== null && fieldRef
!= null) {
451 deserialized
= manager
.GetInstance (fieldRef
.FieldName
);
452 if (deserialized
== null) {
453 object fieldHolder
= DeserializeExpression (manager
, null, fieldRef
.TargetObject
);
454 FieldInfo field
= null;
455 if (fieldHolder
is Type
) // static field
456 field
= ((Type
)fieldHolder
).GetField (fieldRef
.FieldName
,
457 BindingFlags
.GetField
| BindingFlags
.Public
| BindingFlags
.Static
);
458 else // instance field
459 field
= fieldHolder
.GetType().GetField (fieldRef
.FieldName
,
460 BindingFlags
.GetField
| BindingFlags
.Public
| BindingFlags
.Instance
);
462 deserialized
= field
.GetValue (fieldHolder
);
464 if (deserialized
== null)
465 ReportError (manager
, "Field '" + fieldRef
.FieldName
+ "' not initialized prior to reference");
469 // CodePrimitiveExpression
471 CodePrimitiveExpression primitiveExp
= expression
as CodePrimitiveExpression
;
472 if (deserialized
== null && primitiveExp
!= null)
473 deserialized
= primitiveExp
.Value
;
475 // CodePropertyReferenceExpression
477 CodePropertyReferenceExpression propRef
= expression
as CodePropertyReferenceExpression
;
478 if (deserialized
== null && propRef
!= null) {
479 object target
= DeserializeExpression (manager
, null, propRef
.TargetObject
);
480 if (target
!= null && target
!= _errorMarker
) {
482 if (target
is Type
) {
483 PropertyInfo property
= ((Type
)target
).GetProperty (propRef
.PropertyName
,
484 BindingFlags
.GetProperty
|
485 BindingFlags
.Public
| BindingFlags
.Static
);
486 if (property
!= null) {
487 deserialized
= property
.GetValue (null, null);
491 // NRefactory seems to produce PropertyReferences to reference some fields and enums
493 FieldInfo field
= ((Type
)target
).GetField (propRef
.PropertyName
,
494 BindingFlags
.GetField
| BindingFlags
.Public
| BindingFlags
.Static
);
496 deserialized
= field
.GetValue (null);
500 PropertyDescriptor property
= TypeDescriptor
.GetProperties (target
)[propRef
.PropertyName
];
501 if (property
!= null) {
502 deserialized
= property
.GetValue (target
);
506 FieldInfo field
= target
.GetType().GetField (propRef
.PropertyName
,
507 BindingFlags
.GetField
| BindingFlags
.Public
| BindingFlags
.Instance
);
509 deserialized
= field
.GetValue (null);
515 ReportError (manager
, "Missing field '" + propRef
.PropertyName
+ " 'in type " +
516 (target
is Type
? ((Type
)target
).Name
: target
.GetType ().Name
) + "'");
517 errorOccurred
= true;
522 // CodeObjectCreateExpression
524 CodeObjectCreateExpression createExpr
= expression
as CodeObjectCreateExpression
;
525 if (deserialized
== null && createExpr
!= null) {
526 Type type
= manager
.GetType (createExpr
.CreateType
.BaseType
);
528 ReportError (manager
, "Type '" + createExpr
.CreateType
.BaseType
+ "' not found." +
529 "Are you missing a reference?");
530 errorOccurred
= true;
532 object[] arguments
= new object[createExpr
.Parameters
.Count
];
533 for (int i
=0; i
< createExpr
.Parameters
.Count
; i
++) {
534 arguments
[i
] = this.DeserializeExpression (manager
, null, createExpr
.Parameters
[i
]);
535 if (arguments
[i
] == _errorMarker
) {
536 errorOccurred
= true;
540 if (!errorOccurred
) {
541 bool addToContainer
= false;
542 if (typeof(IComponent
).IsAssignableFrom (type
))
543 addToContainer
= true;
544 deserialized
= this.DeserializeInstance (manager
, type
, arguments
, name
, addToContainer
);
545 if (deserialized
== _errorMarker
|| deserialized
== null) {
546 string info
= "Type to create: " + createExpr
.CreateType
.BaseType
+ System
.Environment
.NewLine
+
547 "Name: " + name
+ System
.Environment
.NewLine
+
548 "addToContainer: " + addToContainer
.ToString () + System
.Environment
.NewLine
+
549 "Parameters Count: " + createExpr
.Parameters
.Count
+ System
.Environment
.NewLine
;
551 for (int i
=0; i
< arguments
.Length
; i
++) {
552 info
+= "Parameter Number: " + i
.ToString () + System
.Environment
.NewLine
+
553 "Parameter Type: " + (arguments
[i
] == null ? "null" : arguments
[i
].GetType ().Name
) +
554 System
.Environment
.NewLine
+
555 "Parameter '" + i
.ToString () + "' Value: " + arguments
[i
].ToString () + System
.Environment
.NewLine
;
557 ReportError (manager
,
558 "Unable to create an instance of type '" + createExpr
.CreateType
.BaseType
+ "'",
560 errorOccurred
= true;
566 // CodeArrayCreateExpression
568 CodeArrayCreateExpression arrayCreateExpr
= expression
as CodeArrayCreateExpression
;
569 if (deserialized
== null && arrayCreateExpr
!= null) {
570 Type arrayType
= manager
.GetType (arrayCreateExpr
.CreateType
.BaseType
);
571 if (arrayType
== null) {
572 ReportError (manager
, "Type '" + arrayCreateExpr
.CreateType
.BaseType
+ "' not found." +
573 "Are you missing a reference?");
574 errorOccurred
= true;
576 ArrayList initializers
= new ArrayList ();
577 Type elementType
= arrayType
.GetElementType ();
578 deserialized
= Array
.CreateInstance (arrayType
, arrayCreateExpr
.Initializers
.Count
);
579 for (int i
= 0; i
< arrayCreateExpr
.Initializers
.Count
; i
++) {
580 object element
= this.DeserializeExpression (manager
, null, arrayCreateExpr
.Initializers
[i
]);
581 errorOccurred
= (element
== _errorMarker
);
582 if (!errorOccurred
) {
583 if (arrayType
.IsInstanceOfType (element
)) {
584 initializers
.Add (element
);
586 ReportError (manager
,
587 "Array initializer element type incompatible with array type.",
588 "Array Type: " + arrayType
.Name
+ System
.Environment
.NewLine
+
589 "Array Element Type: " + elementType
+ System
.Environment
.NewLine
+
590 "Initializer Type: " + (element
== null ? "null" : element
.GetType ().Name
));
591 errorOccurred
= true;
596 initializers
.CopyTo ((Array
)deserialized
, 0);
600 // CodeMethodInvokeExpression
602 CodeMethodInvokeExpression methodExpr
= expression
as CodeMethodInvokeExpression
;
603 if (deserialized
== null && methodExpr
!= null) {
604 object target
= this.DeserializeExpression (manager
, null, methodExpr
.Method
.TargetObject
);
605 object[] parameters
= null;
606 if (target
== _errorMarker
|| target
== null) {
607 errorOccurred
= true;
609 parameters
= new object[methodExpr
.Parameters
.Count
];
610 for (int i
=0; i
< methodExpr
.Parameters
.Count
; i
++) {
611 parameters
[i
] = this.DeserializeExpression (manager
, null, methodExpr
.Parameters
[i
]);
612 if (parameters
[i
] == _errorMarker
) {
613 errorOccurred
= true;
619 if (!errorOccurred
) {
620 MethodInfo method
= null;
621 if (target
is Type
) {
622 method
= GetExactMethod ((Type
)target
, methodExpr
.Method
.MethodName
,
623 BindingFlags
.InvokeMethod
| BindingFlags
.Public
| BindingFlags
.Static
,
626 method
= GetExactMethod (target
.GetType(), methodExpr
.Method
.MethodName
,
627 BindingFlags
.InvokeMethod
| BindingFlags
.Public
| BindingFlags
.Instance
,
631 if (method
!= null) {
632 deserialized
= method
.Invoke (target
, parameters
);
635 "Method Name: " + methodExpr
.Method
.MethodName
+ System
.Environment
.NewLine
+
636 "Method is: " + (target
is Type
? "static" : "instance") + System
.Environment
.NewLine
+
637 "Method Holder Type: " + (target
is Type
? ((Type
)target
).Name
: target
.GetType ().Name
) + System
.Environment
.NewLine
+
638 "Parameters Count: " + methodExpr
.Parameters
.Count
+ System
.Environment
.NewLine
+
639 System
.Environment
.NewLine
;
641 for (int i
= 0; i
< parameters
.Length
; i
++) {
642 info
+= "Parameter Number: " + i
.ToString () + System
.Environment
.NewLine
+
643 "Parameter Type: " + (parameters
[i
] == null ? "null" : parameters
[i
].GetType ().Name
) +
644 System
.Environment
.NewLine
+
645 "Parameter " + i
.ToString () + " Value: " + parameters
[i
].ToString () + System
.Environment
.NewLine
;
647 ReportError (manager
,
648 "Method '" + methodExpr
.Method
.MethodName
+ "' missing in type '" +
649 (target
is Type
? ((Type
)target
).Name
: target
.GetType ().Name
+ "'"),
651 errorOccurred
= true;
656 // CodeTypeReferenceExpression
658 CodeTypeReferenceExpression typeRef
= expression
as CodeTypeReferenceExpression
;
659 if (deserialized
== null && typeRef
!= null) {
660 deserialized
= manager
.GetType (typeRef
.Type
.BaseType
);
661 if (deserialized
== null) {
662 ReportError (manager
, "Type '" + typeRef
.Type
.BaseType
+ "' not found." +
663 "Are you missing a reference?");
664 errorOccurred
= true;
668 // CodeCastExpression
670 CodeCastExpression castExpr
= expression
as CodeCastExpression
;
671 if (deserialized
== null && castExpr
!= null) {
672 Type targetType
= manager
.GetType (castExpr
.TargetType
.BaseType
);
673 object instance
= DeserializeExpression (manager
, null, castExpr
.Expression
);
674 if (instance
!= null && instance
!= _errorMarker
&& targetType
!= null) {
675 IConvertible convertible
= instance
as IConvertible
;
676 if (convertible
!= null) {
678 instance
= convertible
.ToType (targetType
, null);
680 errorOccurred
= true;
683 errorOccurred
= true;
686 ReportError (manager
, "Unable to convert type '" + instance
.GetType ().Name
+
687 "' to type '" + castExpr
.TargetType
.BaseType
+ "'",
688 "Target Type: " + castExpr
.TargetType
.BaseType
+ System
.Environment
.NewLine
+
689 "Instance Type: " + (instance
== null ? "null" : instance
.GetType ().Name
) + System
.Environment
.NewLine
+
690 "Instance Value: " + (instance
== null ? "null" : instance
.ToString()) + System
.Environment
.NewLine
+
691 "Instance is IConvertible: " + (instance
is IConvertible
).ToString());
694 deserialized
= instance
;
699 // CodeBinaryOperatorExpression
701 CodeBinaryOperatorExpression binOperator
= expression
as CodeBinaryOperatorExpression
;
702 if (deserialized
== null && binOperator
!= null) {
703 string errorText
= null;
704 IConvertible left
= null;
705 IConvertible right
= null;
706 switch (binOperator
.Operator
) {
707 case CodeBinaryOperatorType
.BitwiseOr
:
708 left
= DeserializeExpression (manager
, null, binOperator
.Left
) as IConvertible
;
709 right
= DeserializeExpression (manager
, null, binOperator
.Right
) as IConvertible
;
710 if (left
is Enum
&& right
is Enum
) {
711 deserialized
= Enum
.ToObject (left
.GetType (), Convert
.ToInt64 (left
) | Convert
.ToInt64 (right
));
713 errorText
= "CodeBinaryOperatorType.BitwiseOr allowed only on Enum types";
714 errorOccurred
= true;
718 errorText
= "Unsupported CodeBinaryOperatorType: " + binOperator
.Operator
.ToString ();
719 errorOccurred
= true;
724 string info
= "BinaryOperator Type: " + binOperator
.Operator
.ToString() + System
.Environment
.NewLine
+
725 "Left Type: " + (left
== null ? "null" : left
.GetType().Name
) + System
.Environment
.NewLine
+
726 "Left Value: " + (left
== null ? "null" : left
.ToString ()) + System
.Environment
.NewLine
+
727 "Left Expression Type: " + binOperator
.Left
.GetType ().Name
+ System
.Environment
.NewLine
+
728 "Right Type: " + (right
== null ? "null" : right
.GetType().Name
) + System
.Environment
.NewLine
+
729 "Right Value: " + (right
== null ? "null" : right
.ToString ()) + System
.Environment
.NewLine
+
730 "Right Expression Type: " + binOperator
.Right
.GetType ().Name
;
731 ReportError (manager
, errorText
, info
);
736 if (!errorOccurred
) {
737 if (deserialized
== null && !(expression
is CodePrimitiveExpression
) && !(expression
is CodeMethodInvokeExpression
)) {
738 ReportError (manager
, "Unsupported Expression Type: " + expression
.GetType ().Name
);
739 errorOccurred
= true;
744 deserialized
= _errorMarker
;
748 // Searches for a method on type that matches argument types
750 private MethodInfo
GetExactMethod (Type type
, string methodName
, BindingFlags flags
, ICollection argsCollection
)
752 object[] arguments
= null;
753 Type
[] types
= Type
.EmptyTypes
;
755 if (argsCollection
!= null) {
756 arguments
= new object[argsCollection
.Count
];
757 types
= new Type
[argsCollection
.Count
];
758 argsCollection
.CopyTo (arguments
, 0);
760 for (int i
=0; i
< arguments
.Length
; i
++) {
761 if (arguments
[i
] == null)
764 types
[i
] = arguments
[i
].GetType ();
768 return type
.GetMethod (methodName
, flags
, null, types
, null);
771 protected void DeserializeStatement (IDesignerSerializationManager manager
, CodeStatement statement
)
773 if (statement
== null)
774 throw new ArgumentNullException ("statement");
776 throw new ArgumentNullException ("manager");
778 // CodeAssignStatement
780 CodeAssignStatement assignment
= statement
as CodeAssignStatement
;
781 if (assignment
!= null)
782 DeserializeAssignmentStatement (manager
, assignment
);
784 // CodeExpressionStatement
786 CodeExpressionStatement expression
= statement
as CodeExpressionStatement
;
787 if (expression
!= null)
788 this.DeserializeExpression (manager
, null, expression
.Expression
);
790 // CodeAttachEventStatement
792 CodeAttachEventStatement attachStatement
= statement
as CodeAttachEventStatement
;
793 if (attachStatement
!= null) {
794 string methodName
= null;
796 CodeObjectCreateExpression createExpr
= attachStatement
.Listener
as CodeObjectCreateExpression
;
797 if (createExpr
!= null && createExpr
.Parameters
.Count
== 1 ) { // += new EventType (method)
798 CodeMethodReferenceExpression handlerRef
= createExpr
.Parameters
[0] as CodeMethodReferenceExpression
;
799 if (handlerRef
!= null)
800 methodName
= handlerRef
.MethodName
;
803 CodeDelegateCreateExpression delegateCreateExpr
= attachStatement
.Listener
as CodeDelegateCreateExpression
;
804 if (delegateCreateExpr
!= null)// += new EventType (method)
805 methodName
= delegateCreateExpr
.MethodName
;
807 CodeMethodReferenceExpression methodRef
= attachStatement
.Listener
as CodeMethodReferenceExpression
;
808 if (methodRef
!= null) // += method
809 methodName
= methodRef
.MethodName
;
811 object component
= DeserializeExpression (manager
, null, attachStatement
.Event
.TargetObject
);
812 if (component
!= null && component
!= _errorMarker
&& methodName
!= null) {
814 EventDescriptor eventDescriptor
= TypeDescriptor
.GetEvents (component
)[attachStatement
.Event
.EventName
];
815 if (eventDescriptor
!= null) {
816 IEventBindingService service
= manager
.GetService (typeof (IEventBindingService
)) as IEventBindingService
;
818 service
.GetEventProperty (eventDescriptor
).SetValue (component
, methodName
);
820 error
= "IEventBindingService missing";
822 error
= "No event '" + attachStatement
.Event
.EventName
+
823 "' found in type '" + component
.GetType ().Name
+ "'";
827 ReportError (manager
, error
, "Method Name: " + methodName
+ System
.Environment
.NewLine
+
828 "Event Name: " + attachStatement
.Event
.EventName
+ System
.Environment
.NewLine
+
829 "Listener Expression Type: " + methodRef
.GetType ().Name
+ System
.Environment
.NewLine
+
830 "Event Holder Type: " + component
.GetType ().Name
+ System
.Environment
.NewLine
+
831 "Event Holder Expression Type: " + attachStatement
.Event
.TargetObject
.GetType ().Name
);
837 private void DeserializeAssignmentStatement (IDesignerSerializationManager manager
, CodeAssignStatement statement
)
839 CodeExpression leftExpr
= statement
.Left
;
841 // Assign to a Property
843 CodePropertyReferenceExpression propRef
= leftExpr
as CodePropertyReferenceExpression
;
844 if (propRef
!= null) {
845 object propertyHolder
= DeserializeExpression (manager
, null, propRef
.TargetObject
);
847 if (propertyHolder
!= null && propertyHolder
!= _errorMarker
)
848 value = DeserializeExpression (manager
, null, statement
.Right
);
850 if (value != null && value != _errorMarker
&& propertyHolder
!= null) {
851 PropertyDescriptor property
= TypeDescriptor
.GetProperties (propertyHolder
)[propRef
.PropertyName
];
852 if (property
!= null) {
853 property
.SetValue (propertyHolder
, value);
855 ReportError (manager
,
856 "Missing property '" + propRef
.PropertyName
+
857 "' in type '" + propertyHolder
.GetType ().Name
+ "'");
864 CodeFieldReferenceExpression fieldRef
= leftExpr
as CodeFieldReferenceExpression
;
865 if (fieldRef
!= null && fieldRef
.FieldName
!= null) {
866 // Note that if the Right expression is a CodeCreationExpression the component will be created in this call
868 object fieldHolder
= DeserializeExpression (manager
, null, fieldRef
.TargetObject
);
870 if (fieldHolder
!= null && fieldHolder
!= _errorMarker
)
871 value = DeserializeExpression (manager
, fieldRef
.FieldName
, statement
.Right
);
872 FieldInfo field
= null;
874 RootContext context
= manager
.Context
[typeof (RootContext
)] as RootContext
;
875 if (fieldHolder
!= null && fieldHolder
!= _errorMarker
&& value != _errorMarker
) {
876 if (fieldRef
.TargetObject
is CodeThisReferenceExpression
&& context
!= null && context
.Value
== fieldHolder
) {
877 // Do not deserialize the fields of the root component, because the root component type
878 // is actually an instance of the its parent type, e.g: CustomControl : _UserControl_
879 // and thus it doesn't contain the fields. The trick is that once DeserializeExpression
880 // is called on a CodeObjectCreateExpression the component is created and is added to the name-instance
884 if (fieldHolder
is Type
) // static field
885 field
= ((Type
)fieldHolder
).GetField (fieldRef
.FieldName
,
886 BindingFlags
.GetField
| BindingFlags
.Public
| BindingFlags
.Static
);
887 else // instance field
888 field
= fieldHolder
.GetType().GetField (fieldRef
.FieldName
,
889 BindingFlags
.GetField
| BindingFlags
.Public
| BindingFlags
.Instance
);
891 field
.SetValue (fieldHolder
, value);
893 ReportError (manager
, "Field '" + fieldRef
.FieldName
+ "' missing in type '" +
894 fieldHolder
.GetType ().Name
+ "'",
895 "Field Name: " + fieldRef
.FieldName
+ System
.Environment
.NewLine
+
896 "Field is: " + (fieldHolder
is Type
? "static" : "instance") + System
.Environment
.NewLine
+
897 "Field Value: " + (value == null ? "null" : value.ToString()) + System
.Environment
.NewLine
+
898 "Field Holder Type: " + fieldHolder
.GetType ().Name
+ System
.Environment
.NewLine
+
899 "Field Holder Expression Type: " + fieldRef
.TargetObject
.GetType ().Name
);
905 // Assign to a Variable
907 CodeVariableReferenceExpression varRef
= leftExpr
as CodeVariableReferenceExpression
;
908 if (varRef
!= null && varRef
.VariableName
!= null) {
909 object value = DeserializeExpression (manager
, varRef
.VariableName
, statement
.Right
);
910 // If .Right is not CodeObjectCreateExpression the instance won't be assigned a name,
911 // so do it ourselves
912 if (value != _errorMarker
&& manager
.GetName (value) == null)
913 manager
.SetName (value, varRef
.VariableName
);
917 internal void ReportError (IDesignerSerializationManager manager
, string message
)
919 this.ReportError (manager
, message
, String
.Empty
);
922 internal void ReportError (IDesignerSerializationManager manager
, string message
, string details
)
925 throw new Exception (message
);
926 } catch (Exception e
) {
927 e
.Data
["Details"] = message
+ Environment
.NewLine
+ Environment
.NewLine
+ details
;
928 manager
.ReportError (e
);
932 #region Resource Serialization - TODO
933 protected CodeExpression
SerializeToResourceExpression (IDesignerSerializationManager manager
, object value)
935 throw new NotImplementedException ();
938 protected CodeExpression
SerializeToResourceExpression (IDesignerSerializationManager manager
, object value,
939 bool ensureInvariant
)
941 throw new NotImplementedException ();
944 protected void SerializePropertiesToResources (IDesignerSerializationManager manager
, CodeStatementCollection statements
,
945 object value, Attribute
[] filter
)
947 throw new NotImplementedException ();
950 protected void SerializeResource (IDesignerSerializationManager manager
, string resourceName
, object value)
952 throw new NotImplementedException ();
955 protected void SerializeResourceInvariant (IDesignerSerializationManager manager
, string resourceName
, object value)
957 throw new NotImplementedException ();
960 protected void DeserializePropertiesFromResources (IDesignerSerializationManager manager
, object value, Attribute
[] filter
)
962 throw new NotImplementedException ();