2010-04-06 Jb Evain <jbevain@novell.com>
[mcs.git] / class / System.Design / System.ComponentModel.Design.Serialization / CodeDomSerializerBase.cs
blobdbf0979cccb9ff2f891b38f2cc916a4c1b890f8c
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
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.
30 #if NET_2_0
32 using System;
33 using System.Collections;
34 using System.Reflection;
35 using System.ComponentModel;
36 using System.ComponentModel.Design;
38 using System.CodeDom;
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)
52 return false;
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)
73 if (manager == null)
74 throw new ArgumentNullException ("manager");
76 CodeExpression expression = null;
77 if (instance != 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);
101 else
102 contextStatements.Add (statement);
106 if (expression == null && instance != null)
107 expression = this.GetExpression (manager, instance); // 4
108 } else {
109 ReportError (manager, "No serializer found for type '" + instance.GetType ().Name + "'");
112 return expression;
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);
123 else {
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;
129 break;
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;
138 break;
142 // if there is metadata modification in the instance then create the specified serializer instead of the one
143 // in the Type.
144 if (attrType != null && attrInstance != null && attrType.SerializerTypeName != attrInstance.SerializerTypeName)
145 serializer = Activator.CreateInstance (manager.GetType (attrInstance.SerializerTypeName)) as CodeDomSerializer;
146 else
147 serializer = this.GetSerializer (manager, instance.GetType ());
150 return serializer;
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)
160 if (manager == null)
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]);
197 return expression;
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)
209 if (manager == null)
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");
235 if (manager == null)
236 throw new ArgumentNullException ("manager");
238 if (this.GetExpression (manager, instance) != null)
239 return true;
240 else
241 return false;
244 protected CodeExpression SerializeCreationExpression (IDesignerSerializationManager manager, object value, out bool isComplete)
246 if (value == null)
247 throw new ArgumentNullException ("value");
248 if (manager == null)
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);
259 else
260 ReportError (manager, "Unable to serialize to InstanceDescriptor",
261 "Value Type: " + value.GetType ().Name + System.Environment.NewLine +
262 "Value (ToString): " + value.ToString ());
263 } else {
264 if (value.GetType().GetConstructor (Type.EmptyTypes) != null)
265 expression = new CodeObjectCreateExpression (value.GetType ().FullName, new CodeExpression[0]);
266 isComplete = false;
268 return expression;
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;
293 return expression;
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];
302 int i = 0;
303 foreach (object parameter in parameters) {
304 expressions[i] = this.SerializeToExpression (manager, parameter);
305 i++;
309 return expressions;
312 protected void SerializeEvent (IDesignerSerializationManager manager, CodeStatementCollection statements,
313 object value, EventDescriptor descriptor)
315 if (descriptor == null)
316 throw new ArgumentNullException ("descriptor");
317 if (value == null)
318 throw new ArgumentNullException ("value");
319 if (statements == null)
320 throw new ArgumentNullException ("statements");
321 if (manager == null)
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)
332 if (filter == null)
333 throw new ArgumentNullException ("filter");
334 if (value == null)
335 throw new ArgumentNullException ("value");
336 if (statements == null)
337 throw new ArgumentNullException ("statements");
338 if (manager == null)
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");
351 if (value == null)
352 throw new ArgumentNullException ("value");
353 if (statements == null)
354 throw new ArgumentNullException ("statements");
355 if (manager == null)
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)
367 if (filter == null)
368 throw new ArgumentNullException ("filter");
369 if (value == null)
370 throw new ArgumentNullException ("value");
371 if (statements == null)
372 throw new ArgumentNullException ("statements");
373 if (manager == null)
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)
386 if (type == null)
387 throw new ArgumentNullException ("type");
388 if (manager == null)
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");
398 if (manager == null)
399 throw new ArgumentNullException ("manager");
401 string name = manager.GetName (instance);
402 if (name == null) {
403 INameCreationService service = manager.GetService (typeof (INameCreationService)) as INameCreationService;
404 name = service.CreateName (null, instance.GetType ());
405 if (name == null)
406 name = instance.GetType ().Name.ToLower ();
407 manager.SetName (instance, name);
409 return name;
412 protected object DeserializeExpression (IDesignerSerializationManager manager, string name, CodeExpression expression)
414 if (expression == null)
415 throw new ArgumentNullException ("expression");
416 if (manager == null)
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;
429 } else {
430 IDesignerHost host = manager.GetService (typeof (IDesignerHost)) as IDesignerHost;
431 if (host != null)
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);
461 if (field != null)
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) {
481 bool found = false;
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);
488 found = true;
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);
495 if (field != null) {
496 deserialized = field.GetValue (null);
497 found = true;
499 } else {
500 PropertyDescriptor property = TypeDescriptor.GetProperties (target)[propRef.PropertyName];
501 if (property != null) {
502 deserialized = property.GetValue (target);
503 found = true;
506 FieldInfo field = target.GetType().GetField (propRef.PropertyName,
507 BindingFlags.GetField | BindingFlags.Public | BindingFlags.Instance);
508 if (field != null) {
509 deserialized = field.GetValue (null);
510 found = true;
514 if (!found) {
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);
527 if (type == null) {
528 ReportError (manager, "Type '" + createExpr.CreateType.BaseType + "' not found." +
529 "Are you missing a reference?");
530 errorOccurred = true;
531 } else {
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;
537 break;
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 + "'",
559 info);
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;
575 } else {
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);
585 } else {
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;
595 if (!errorOccurred)
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;
608 } else {
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;
614 break;
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,
624 parameters);
625 } else {
626 method = GetExactMethod (target.GetType(), methodExpr.Method.MethodName,
627 BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Instance,
628 parameters);
631 if (method != null) {
632 deserialized = method.Invoke (target, parameters);
633 } else {
634 string info =
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 + "'"),
650 info);
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) {
677 try {
678 instance = convertible.ToType (targetType, null);
679 } catch {
680 errorOccurred = true;
682 } else {
683 errorOccurred = true;
685 if (errorOccurred) {
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));
712 } else {
713 errorText = "CodeBinaryOperatorType.BitwiseOr allowed only on Enum types";
714 errorOccurred = true;
716 break;
717 default:
718 errorText = "Unsupported CodeBinaryOperatorType: " + binOperator.Operator.ToString ();
719 errorOccurred = true;
720 break;
723 if (errorOccurred) {
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;
743 if (errorOccurred)
744 deserialized = _errorMarker;
745 return deserialized;
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)
762 types[i] = null;
763 else
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");
775 if (manager == null)
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) {
813 string error = null;
814 EventDescriptor eventDescriptor = TypeDescriptor.GetEvents (component)[attachStatement.Event.EventName];
815 if (eventDescriptor != null) {
816 IEventBindingService service = manager.GetService (typeof (IEventBindingService)) as IEventBindingService;
817 if (service != null)
818 service.GetEventProperty (eventDescriptor).SetValue (component, methodName);
819 else
820 error = "IEventBindingService missing";
821 } else {
822 error = "No event '" + attachStatement.Event.EventName +
823 "' found in type '" + component.GetType ().Name + "'";
826 if (error != null) {
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);
846 object value = null;
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);
854 } else {
855 ReportError (manager,
856 "Missing property '" + propRef.PropertyName +
857 "' in type '" + propertyHolder.GetType ().Name + "'");
862 // Assign to a Field
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);
869 object value = null;
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
881 // table.
883 } else {
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);
890 if (field != null)
891 field.SetValue (fieldHolder, value);
892 else {
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)
924 try {
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 ();
964 #endregion
967 #endif