/// <summary> /// This method actually performs the serialization. When the member is serialized /// the necessary statements will be added to the statements collection. /// </summary> public override void Serialize(IDesignerSerializationManager manager, object value, MemberDescriptor descriptor, CodeStatementCollection statements) { if (manager == null) { throw new ArgumentNullException(nameof(manager)); } if (value == null) { throw new ArgumentNullException(nameof(value)); } if (!(descriptor is EventDescriptor eventToSerialize)) { throw new ArgumentNullException(nameof(descriptor)); } if (statements == null) { throw new ArgumentNullException(nameof(statements)); } try { // If the IEventBindingService is not available, we don't throw - we just don't do anything. if (manager.GetService(typeof(IEventBindingService)) is IEventBindingService eventBindings) { PropertyDescriptor prop = eventBindings.GetEventProperty(eventToSerialize); string methodName = (string)prop.GetValue(value); if (methodName != null) { CodeDomSerializer.Trace("Event {0} bound to {1}", eventToSerialize.Name, methodName); CodeExpression eventTarget = SerializeToExpression(manager, value); CodeDomSerializer.TraceWarningIf(eventTarget == null, "Object has no name and no propery ref in context so we cannot serialize events: {0}", value); if (eventTarget != null) { CodeTypeReference delegateTypeRef = new CodeTypeReference(eventToSerialize.EventType); CodeDelegateCreateExpression delegateCreate = new CodeDelegateCreateExpression(delegateTypeRef, _thisRef, methodName); CodeEventReferenceExpression eventRef = new CodeEventReferenceExpression(eventTarget, eventToSerialize.Name); CodeAttachEventStatement attach = new CodeAttachEventStatement(eventRef, delegateCreate); attach.UserData[typeof(Delegate)] = eventToSerialize.EventType; statements.Add(attach); } } } } catch (Exception e) { // Since we usually go through reflection, don't // show what our engine does, show what caused // the problem. // if (e is TargetInvocationException) { e = e.InnerException; } manager.ReportError(new CodeDomSerializerException(string.Format(SR.SerializerPropertyGenFailed, eventToSerialize.Name, e.Message), manager)); } }
/// <summary> /// This serializes the given property on this object. /// </summary> private void SerializeNormalProperty(IDesignerSerializationManager manager, object value, PropertyDescriptor property, CodeStatementCollection statements) { using (CodeDomSerializer.TraceScope("CodeDomSerializer::" + nameof(SerializeProperty))) { CodeExpression target = SerializeToExpression(manager, value); CodeDomSerializer.TraceWarningIf(target == null, "Unable to serialize target for property {0}", property.Name); if (target != null) { CodeExpression propertyRef = new CodePropertyReferenceExpression(target, property.Name); CodeExpression serializedPropertyValue = null; // First check for a member relationship service to see if this property // is related to another member. If it is, then we will use that // relationship to construct the property assign statement. if // it isn't, then we're serialize ourselves. if (manager.GetService(typeof(MemberRelationshipService)) is MemberRelationshipService relationships) { MemberRelationship relationship = relationships[value, property]; if (relationship != MemberRelationship.Empty) { CodeExpression rhsTarget = SerializeToExpression(manager, relationship.Owner); if (rhsTarget != null) { serializedPropertyValue = new CodePropertyReferenceExpression(rhsTarget, relationship.Member.Name); } } } if (serializedPropertyValue == null) { // Serialize the value of this property into a code expression. If we can't get one, // then we won't serialize the property. // object propValue = GetPropertyValue(manager, property, value, out bool validValue); if (validValue) { ExpressionContext tree = null; if (propValue != value) { // make sure the value isn't the object or we'll end up printing // this property instead of the value. tree = new ExpressionContext(propertyRef, property.PropertyType, value); manager.Context.Push(tree); } try { serializedPropertyValue = SerializeToExpression(manager, propValue); } finally { if (tree != null) { Debug.Assert(manager.Context.Current == tree, "Context stack corrupted."); manager.Context.Pop(); } } } } if (serializedPropertyValue != null) { CodeAssignStatement assign = new CodeAssignStatement(propertyRef, serializedPropertyValue); statements.Add(assign); } } } }
/// <summary> /// This serializes the given property on this object. /// </summary> private void SerializeExtenderProperty(IDesignerSerializationManager manager, object value, PropertyDescriptor property, CodeStatementCollection statements) { AttributeCollection attributes = property.Attributes; using (CodeDomSerializer.TraceScope("PropertyMemberCodeDomSerializer::" + nameof(SerializeExtenderProperty))) { ExtenderProvidedPropertyAttribute exAttr = (ExtenderProvidedPropertyAttribute)attributes[typeof(ExtenderProvidedPropertyAttribute)]; // Extender properties are method invokes on a target "extender" object. // CodeExpression extender = SerializeToExpression(manager, exAttr.Provider); CodeExpression extended = SerializeToExpression(manager, value); CodeDomSerializer.TraceWarningIf(extender == null, "Extender object {0} could not be serialized.", manager.GetName(exAttr.Provider)); CodeDomSerializer.TraceWarningIf(extended == null, "Extended object {0} could not be serialized.", manager.GetName(value)); if (extender != null && extended != null) { CodeMethodReferenceExpression methodRef = new CodeMethodReferenceExpression(extender, "Set" + property.Name); object propValue = GetPropertyValue(manager, property, value, out bool validValue); CodeExpression serializedPropertyValue = null; // Serialize the value of this property into a code expression. If we can't get one, // then we won't serialize the property. if (validValue) { ExpressionContext tree = null; if (propValue != value) { // make sure the value isn't the object or we'll end up printing // this property instead of the value. tree = new ExpressionContext(methodRef, property.PropertyType, value); manager.Context.Push(tree); } try { serializedPropertyValue = SerializeToExpression(manager, propValue); } finally { if (tree != null) { Debug.Assert(manager.Context.Current == tree, "Context stack corrupted."); manager.Context.Pop(); } } } if (serializedPropertyValue != null) { CodeMethodInvokeExpression methodInvoke = new CodeMethodInvokeExpression { Method = methodRef }; methodInvoke.Parameters.Add(extended); methodInvoke.Parameters.Add(serializedPropertyValue); statements.Add(methodInvoke); } } } }
/// <summary> /// This serializes the given property on this object as a content property. /// </summary> private void SerializeContentProperty(IDesignerSerializationManager manager, object value, PropertyDescriptor property, bool isExtender, CodeStatementCollection statements) { CodeDomSerializer.Trace("Property is marked as Visibility.Content. Recursing."); object propertyValue = GetPropertyValue(manager, property, value, out bool validValue); // For persist contents objects, we don't just serialize the properties on the object; we // serialize everything. // CodeDomSerializer serializer = null; if (propertyValue == null) { CodeDomSerializer.TraceError("Property {0} is marked as Visibility.Content but it is returning null.", property.Name); string name = manager.GetName(value); if (name == null) { name = value.GetType().FullName; } manager.ReportError(new CodeDomSerializerException(string.Format(SR.SerializerNullNestedProperty, name, property.Name), manager)); } else { serializer = (CodeDomSerializer)manager.GetSerializer(propertyValue.GetType(), typeof(CodeDomSerializer)); if (serializer != null) { // Create a property reference expression and push it on the context stack. // This allows the serializer to gain some context as to what it should be // serializing. CodeExpression target = SerializeToExpression(manager, value); if (target == null) { CodeDomSerializer.TraceWarning("Unable to convert value to expression object"); } else { CodeExpression propertyRef = null; if (isExtender) { CodeDomSerializer.Trace("Content property is an extender."); ExtenderProvidedPropertyAttribute exAttr = (ExtenderProvidedPropertyAttribute)property.Attributes[typeof(ExtenderProvidedPropertyAttribute)]; // Extender properties are method invokes on a target "extender" object. // CodeExpression extender = SerializeToExpression(manager, exAttr.Provider); CodeExpression extended = SerializeToExpression(manager, value); CodeDomSerializer.TraceWarningIf(extender == null, "Extender object {0} could not be serialized.", manager.GetName(exAttr.Provider)); CodeDomSerializer.TraceWarningIf(extended == null, "Extended object {0} could not be serialized.", manager.GetName(value)); if (extender != null && extended != null) { CodeMethodReferenceExpression methodRef = new CodeMethodReferenceExpression(extender, "Get" + property.Name); CodeMethodInvokeExpression methodInvoke = new CodeMethodInvokeExpression { Method = methodRef }; methodInvoke.Parameters.Add(extended); propertyRef = methodInvoke; } } else { propertyRef = new CodePropertyReferenceExpression(target, property.Name); } if (propertyRef != null) { ExpressionContext tree = new ExpressionContext(propertyRef, property.PropertyType, value, propertyValue); manager.Context.Push(tree); object result = null; try { SerializeAbsoluteContext absolute = (SerializeAbsoluteContext)manager.Context[typeof(SerializeAbsoluteContext)]; if (IsSerialized(manager, propertyValue, absolute != null)) { result = GetExpression(manager, propertyValue); } else { result = serializer.Serialize(manager, propertyValue); } } finally { Debug.Assert(manager.Context.Current == tree, "Serializer added a context it didn't remove."); manager.Context.Pop(); } if (result is CodeStatementCollection csc) { foreach (CodeStatement statement in csc) { statements.Add(statement); } } else { if (result is CodeStatement cs) { statements.Add(cs); } } } } } else { CodeDomSerializer.TraceError("Property {0} is marked as Visibilty.Content but there is no serializer for it.", property.Name); manager.ReportError(new CodeDomSerializerException(string.Format(SR.SerializerNoSerializerForComponent, property.PropertyType.FullName), manager)); } } }