1 //
2 // System.ComponentModel.Design.Serialization.PropertyCodeDomSerializer
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 
31 using System;
32 using System.ComponentModel;
33 using System.ComponentModel.Design;
34 
35 using System.CodeDom;
36 
37 namespace System.ComponentModel.Design.Serialization
38 {
39 	internal class PropertyCodeDomSerializer : MemberCodeDomSerializer
40 	{
41 
PropertyCodeDomSerializer()42 		public PropertyCodeDomSerializer ()
43 		{
44 		}
45 
Serialize(IDesignerSerializationManager manager, object value, MemberDescriptor descriptor, CodeStatementCollection statements)46 		public override void Serialize (IDesignerSerializationManager manager, object value, MemberDescriptor descriptor, CodeStatementCollection statements)
47 		{
48 			if (manager == null)
49 				throw new ArgumentNullException ("manager");
50 			if (value == null)
51 				throw new ArgumentNullException ("value");
52 			if (descriptor == null)
53 				throw new ArgumentNullException ("descriptor");
54 			if (statements == null)
55 				throw new ArgumentNullException ("statements");
56 
57 			PropertyDescriptor property = (PropertyDescriptor) descriptor;
58 
59 			if (property.Attributes.Contains (DesignerSerializationVisibilityAttribute.Content))
60 				SerializeContentProperty (manager, value, property, statements);
61 			else
62 				SerializeNormalProperty (manager, value, property, statements);
63 		}
64 
65 
SerializeNormalProperty(IDesignerSerializationManager manager, object instance, PropertyDescriptor descriptor, CodeStatementCollection statements)66 		private void SerializeNormalProperty (IDesignerSerializationManager manager,
67 						      object instance, PropertyDescriptor descriptor, CodeStatementCollection statements)
68 		{
69 			CodeAssignStatement assignment = new CodeAssignStatement ();
70 
71 			CodeExpression leftSide = null;
72 			CodePropertyReferenceExpression propRef = null;
73 			ExpressionContext expression = manager.Context[typeof (ExpressionContext)] as ExpressionContext;
74 			RootContext root = manager.Context[typeof (RootContext)] as RootContext;
75 
76 			if (expression != null && expression.PresetValue == instance && expression.Expression != null) {
77 				leftSide = new CodePropertyReferenceExpression (expression.Expression, descriptor.Name);
78 			} else if (root != null && root.Value == instance) {
79 				leftSide = new CodePropertyReferenceExpression (root.Expression, descriptor.Name);
80 			} else {
81 				propRef = new CodePropertyReferenceExpression ();
82 				propRef.PropertyName =  descriptor.Name;
83 				propRef.TargetObject = base.SerializeToExpression (manager, instance);
84 				leftSide = propRef;
85 			}
86 
87 			CodeExpression rightSide = null;
88 
89 			MemberRelationship relationship = GetRelationship (manager, instance, descriptor);
90 			if (!relationship.IsEmpty) {
91 				propRef = new CodePropertyReferenceExpression ();
92 				propRef.PropertyName = relationship.Member.Name;
93 				propRef.TargetObject = base.SerializeToExpression (manager, relationship.Owner);
94 				rightSide = propRef;
95 			} else {
96 				rightSide = base.SerializeToExpression (manager, descriptor.GetValue (instance));
97 			}
98 
99 			if (rightSide == null || leftSide == null) {
100 				base.ReportError (manager, "Cannot serialize " + ((IComponent)instance).Site.Name + "." + descriptor.Name,
101 						  "Property Name: " + descriptor.Name + System.Environment.NewLine +
102 						  "Property Type: " + descriptor.PropertyType.Name + System.Environment.NewLine);
103 			} else  {
104 				assignment.Left = leftSide;
105 				assignment.Right = rightSide;
106 				statements.Add (assignment);
107 			}
108 		}
109 
SerializeContentProperty(IDesignerSerializationManager manager, object instance, PropertyDescriptor descriptor, CodeStatementCollection statements)110 		private void SerializeContentProperty (IDesignerSerializationManager manager, object instance,
111 						       PropertyDescriptor descriptor, CodeStatementCollection statements)
112 		{
113 			CodePropertyReferenceExpression propRef = new CodePropertyReferenceExpression ();
114 			propRef.PropertyName = descriptor.Name;
115 			object propertyValue = descriptor.GetValue (instance);
116 
117 			ExpressionContext expressionCtx = manager.Context[typeof (ExpressionContext)] as ExpressionContext;
118 			if (expressionCtx != null && expressionCtx.PresetValue == instance)
119 				propRef.TargetObject = expressionCtx.Expression;
120 			else
121 				propRef.TargetObject = base.SerializeToExpression (manager, instance);
122 
123 			CodeDomSerializer serializer = manager.GetSerializer (propertyValue.GetType (), typeof (CodeDomSerializer)) as CodeDomSerializer;
124 			if (propRef.TargetObject != null && serializer != null) {
125 				manager.Context.Push (new ExpressionContext (propRef, propRef.GetType (), null, propertyValue));
126 				object serialized = serializer.Serialize (manager, propertyValue);
127 				manager.Context.Pop ();
128 
129 				CodeStatementCollection serializedStatements = serialized as CodeStatementCollection;
130 				if (serializedStatements != null)
131 					statements.AddRange (serializedStatements);
132 
133 				CodeStatement serializedStatement = serialized as CodeStatement;
134 				if (serializedStatement != null)
135 					statements.Add (serializedStatement);
136 
137 				CodeExpression serializedExpr = serialized as CodeExpression;
138 				if (serializedExpr != null)
139 					statements.Add (new CodeAssignStatement (propRef, serializedExpr));
140 			}
141 		}
142 
ShouldSerialize(IDesignerSerializationManager manager, object value, MemberDescriptor descriptor)143 		public override bool ShouldSerialize (IDesignerSerializationManager manager, object value, MemberDescriptor descriptor)
144 		{
145 			if (manager == null)
146 				throw new ArgumentNullException ("manager");
147 			if (value == null)
148 				throw new ArgumentNullException ("value");
149 			if (descriptor == null)
150 				throw new ArgumentNullException ("descriptor");
151 
152 			PropertyDescriptor property = (PropertyDescriptor) descriptor;
153 
154 			if (property.Attributes.Contains (DesignOnlyAttribute.Yes))
155 				return false;
156 
157 			SerializeAbsoluteContext absolute = manager.Context[typeof (SerializeAbsoluteContext)] as SerializeAbsoluteContext;
158 			if (absolute != null && absolute.ShouldSerialize (descriptor))
159 				return true;
160 
161 			bool result = property.ShouldSerializeValue (value);
162 
163 			if (!result) {
164 				if (!GetRelationship (manager, value, descriptor).IsEmpty)
165 					result = true;
166 			}
167 
168 			return result;
169 		}
170 
GetRelationship(IDesignerSerializationManager manager, object value, MemberDescriptor descriptor)171 		private MemberRelationship GetRelationship (IDesignerSerializationManager manager, object value, MemberDescriptor descriptor)
172 		{
173 			MemberRelationshipService service = manager.GetService (typeof (MemberRelationshipService)) as MemberRelationshipService;
174 			if (service != null)
175 				return service[value, descriptor];
176 			else
177 				return MemberRelationship.Empty;
178 		}
179 	}
180 }
181