Ejemplo n.º 1
0
        /// <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 is null)
            {
                throw new ArgumentNullException(nameof(manager));
            }
            if (value is null)
            {
                throw new ArgumentNullException(nameof(value));
            }
            if (!(descriptor is EventDescriptor eventToSerialize))
            {
                throw new ArgumentNullException(nameof(descriptor));
            }
            if (statements is 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 is 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 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 is null)
            {
                throw new ArgumentNullException(nameof(manager));
            }

            if (value is null)
            {
                throw new ArgumentNullException(nameof(value));
            }

            if (!(descriptor is PropertyDescriptor propertyToSerialize))
            {
                throw new ArgumentNullException(nameof(descriptor));
            }

            if (statements is null)
            {
                throw new ArgumentNullException(nameof(statements));
            }

            try
            {
                ExtenderProvidedPropertyAttribute exAttr = (ExtenderProvidedPropertyAttribute)propertyToSerialize.Attributes[typeof(ExtenderProvidedPropertyAttribute)];
                bool isExtender        = (exAttr != null && exAttr.Provider != null);
                bool serializeContents = propertyToSerialize.Attributes.Contains(DesignerSerializationVisibilityAttribute.Content);

                CodeDomSerializer.Trace("Serializing property {0}", propertyToSerialize.Name);
                if (serializeContents)
                {
                    SerializeContentProperty(manager, value, propertyToSerialize, isExtender, statements);
                }
                else if (isExtender)
                {
                    SerializeExtenderProperty(manager, value, propertyToSerialize, statements);
                }
                else
                {
                    SerializeNormalProperty(manager, value, propertyToSerialize, statements);
                }
            }
            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, propertyToSerialize.Name, e.Message), manager));
            }
        }
        /// <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 is null)
            {
                CodeDomSerializer.TraceError("Property {0} is marked as Visibility.Content but it is returning null.", property.Name);

                string name = manager.GetName(value);

                if (name is 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 is 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 is null, "Extender object {0} could not be serialized.", manager.GetName(exAttr.Provider));
                            CodeDomSerializer.TraceWarningIf(extended is 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));
                }
            }
        }