CodeDomSerializerBase.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ FX-1434 / FX-1434 / 1.0 / untmp / whidbey / REDBITS / ndp / fx / src / Designer / CompMod / System / ComponentModel / Design / Serialization / CodeDomSerializerBase.cs / 3 / CodeDomSerializerBase.cs

                             
//------------------------------------------------------------------------------
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
//  
//-----------------------------------------------------------------------------
 
namespace System.ComponentModel.Design.Serialization { 

    using System; 
    using System.Design;
    using System.Resources;
    using System.CodeDom;
    using System.CodeDom.Compiler; 
    using System.Collections;
    using System.Collections.Generic; 
    using System.ComponentModel; 
    using System.ComponentModel.Design;
    using System.Diagnostics; 
    using System.Diagnostics.CodeAnalysis;
    using System.Globalization;
    using System.Reflection;
    using System.Text; 

    ///  
    ///  
    ///    This base class is used as a shared base between CodeDomSerializer and TypeCodeDomSerializer.
    ///    It is not meant to be publicly derived from. 
    /// 
    [EditorBrowsable(EditorBrowsableState.Never)]
    public abstract class CodeDomSerializerBase {
 
        private static readonly Attribute[] runTimeProperties = new Attribute[] { DesignOnlyAttribute.No };
        private static readonly CodeThisReferenceExpression thisRef = new CodeThisReferenceExpression(); 
        private static TraceSwitch traceSerialization = new TraceSwitch("DesignerSerialization", "Trace design time serialization"); 

        private static Stack traceScope; 

        /// 
        ///    Internal constructor so only we can derive from this class.
        ///  
        internal CodeDomSerializerBase() {
        } 
 
        /// 
        ///  
        ///    This method is invoked during deserialization to obtain an instance of an object.  When this is called, an instance
        ///    of the requested type should be returned.  The default implementation invokes manager.CreateInstance.
        /// 
        protected virtual object DeserializeInstance(IDesignerSerializationManager manager, Type type, object[] parameters, string name, bool addToContainer) { 
            if (manager == null) throw new ArgumentNullException("manager");
 
            if (type == null) throw new ArgumentNullException("type"); 

            return manager.CreateInstance(type, parameters, name, addToContainer); 
        }

        /// 
        /// This routine returns the correct typename given a CodeTypeReference.  It expands the child typenames 
        /// and builds up the clr formatted generic name.  If its not a generic, it just returns BaseType.
        ///  
        internal static string GetTypeNameFromCodeTypeReference(IDesignerSerializationManager manager, CodeTypeReference typeref) { 
            //we do this to avoid an extra gettype for the usual nongeneric case.
            if (typeref.TypeArguments == null || typeref.TypeArguments.Count == 0) { 
                return typeref.BaseType;
            }

            return GetTypeNameFromCodeTypeReferenceHelper(manager, typeref); 
        }
 
        ///  
        /// This helper is used by GetTypeNameFromCodeTypeReference -- do not call this directly.
        ///  
        private static string GetTypeNameFromCodeTypeReferenceHelper(IDesignerSerializationManager manager, CodeTypeReference typeref) {
            if (typeref.TypeArguments == null || typeref.TypeArguments.Count == 0) {
                Type t = manager.GetType(typeref.BaseType);
                //we use the assemblyqualifiedname where we can so that GetType will find it correctly. 
                if (t != null) {
                    return t.AssemblyQualifiedName; 
                } 
                return typeref.BaseType;
            } 

            //create the MyGeneric`2[ part
            StringBuilder typename = new StringBuilder(typeref.BaseType);
            if (!typeref.BaseType.Contains("`")) { 
                typename.Append("`");
                typename.Append(typeref.TypeArguments.Count); 
            } 
            typename.Append("[");
 
            bool first = true;

            //now create each sub-argument part.
            foreach (CodeTypeReference childref in typeref.TypeArguments) { 
                if (!first) {
                    typename.Append(","); 
                } 
                typename.Append("[");
                typename.Append(GetTypeNameFromCodeTypeReferenceHelper(manager, childref)); 
                typename.Append("]");
                first = false;
            }
            typename.Append("]"); 

            //otherwise, we have a generic and we need to format it. 
            return typename.ToString(); 
        }
 
        [SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily")]
        private object DeserializePropertyReferenceExpression(IDesignerSerializationManager manager, CodePropertyReferenceExpression propertyReferenceEx, bool reportError) {
            object result = propertyReferenceEx;
            Trace("Property reference : {0}", propertyReferenceEx.PropertyName); 

            object target = DeserializeExpression(manager, null, propertyReferenceEx.TargetObject); 
 
            if (target != null && !(target is CodeExpression)) {
                // if it's a type, then we've got ourselves a static field... 
                //
                if (!(target is Type)) {
                    PropertyDescriptor prop = TypeDescriptor.GetProperties(target)[propertyReferenceEx.PropertyName];
 
                    if (prop != null) {
                        result = prop.GetValue(target); 
                    } 
                    else {
                        // This could be a protected property on the base class.  Make sure we're 
                        // actually accessing through the base class, and then get the property
                        // directly from reflection.
                        //
                        if (GetExpression(manager, target) is CodeThisReferenceExpression) { 
                            PropertyInfo propInfo = TypeDescriptor.GetReflectionType(target).GetProperty(propertyReferenceEx.PropertyName, BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
 
                            if (propInfo != null) { 
                                result = propInfo.GetValue(target, null);
                            } 
                        }
                    }
                }
                else { 
                    PropertyInfo prop = TypeDescriptor.GetReflectionType((Type)target).GetProperty(propertyReferenceEx.PropertyName, BindingFlags.GetProperty | BindingFlags.Static | BindingFlags.Public);
 
                    if (prop != null) { 
                        result = prop.GetValue(null, null);
                    } 
                }

                if (result == propertyReferenceEx && reportError) {
                    string typeName = (target is Type) ? ((Type)target).FullName : TypeDescriptor.GetReflectionType(target).FullName; 
                    Error(manager, SR.GetString(SR.SerializerNoSuchProperty, typeName, propertyReferenceEx.PropertyName), SR.SerializerNoSuchProperty);
                } 
            } 

            TraceWarningIf(result == propertyReferenceEx, "Could not resolve property {0} to an object instance.", propertyReferenceEx.PropertyName); 
            return result;
        }

        ///  
        /// 
        ///     This is a helper method that will deserialize a given expression.  It deserializes 
        ///     the statement by interpreting and executing the CodeDom expression, returning 
        ///     the results.
        ///  
        [SuppressMessage("Microsoft.Security", "CA2102:CatchNonClsCompliantExceptionsInGeneralHandlers")]
        [SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily")]
        protected object DeserializeExpression(IDesignerSerializationManager manager, string name, CodeExpression expression) {
            object result = expression; 
            using (TraceScope("CodeDomSerializerBase::DeserializeExpression")) {
                // Perf: is -> as changes, change ordering based on possibility of occurance 
                // If you are adding to this, use as instead of is + cast and order new expressions 
                // in order of frequency in typical user code.
                CodePrimitiveExpression primitiveEx; 
                CodePropertyReferenceExpression propertyReferenceEx;
                CodeTypeReferenceExpression typeReferenceEx;
                CodeObjectCreateExpression objectCreateEx;
                CodeArgumentReferenceExpression argumentReferenceEx; 
                CodeFieldReferenceExpression fieldReferenceEx;
                CodeMethodInvokeExpression methodInvokeEx; 
                CodeVariableReferenceExpression variableReferenceEx; 
                CodeCastExpression castEx;
                CodeArrayCreateExpression arrayCreateEx; 
                CodeArrayIndexerExpression arrayIndexerEx;
                CodeBinaryOperatorExpression binaryOperatorEx;
                CodeDelegateInvokeExpression delegateInvokeEx;
                CodeDirectionExpression directionEx; 
                CodeIndexerExpression indexerEx;
                CodeParameterDeclarationExpression parameterDeclaration; 
                CodeTypeOfExpression typeOfExpression; 

                while (result != null) { 
                    if ((primitiveEx = result as CodePrimitiveExpression) != null) {
                        Trace("Primitive.  Value: {0}", (primitiveEx.Value == null ? "(null)" : primitiveEx.Value));
                        result = primitiveEx.Value;
                        break; 
                    }
                    else if ((propertyReferenceEx = result as CodePropertyReferenceExpression) != null) { 
                        result = DeserializePropertyReferenceExpression(manager, propertyReferenceEx, true); 
                        break;
                    } 
                    else if (result is CodeThisReferenceExpression) { //(is -> as doesn't help here, since the cast is different)
                        Trace("'this' reference");

                        RootContext rootExp = (RootContext)manager.Context[typeof(RootContext)]; 

                        if (rootExp != null) { 
                            result = rootExp.Value; 
                        }
                        else { 
                            // Last ditch effort.  Some things have to code gen against "this", such
                            // as event wireups.  Those are always bounda against the root component.
                            IDesignerHost host = manager.GetService(typeof(IDesignerHost)) as IDesignerHost;
                            if (host != null) { 
                                result = host.RootComponent;
                            } 
                        } 

                        if (result == null) { 
                            TraceError("CodeThisReferenceExpression not handled because there is no root context or the root context did not contain an instance.");
                            Error(manager, SR.GetString(SR.SerializerNoRootExpression), SR.SerializerNoRootExpression);
                        }
 
                        break;
                    } 
                    else if ((typeReferenceEx = result as CodeTypeReferenceExpression) != null) { 
                        Trace("TypeReference : {0}", typeReferenceEx.Type.BaseType);
                        result = manager.GetType(GetTypeNameFromCodeTypeReference(manager, typeReferenceEx.Type)); 
                        break;
                    }
                    else if ((objectCreateEx = result as CodeObjectCreateExpression) != null) {
                        Trace("Object create"); 
                        result = null;
 
 
                        Type type = manager.GetType(GetTypeNameFromCodeTypeReference(manager, objectCreateEx.CreateType));
 
                        if (type != null) {
                            object[] parameters = new object[objectCreateEx.Parameters.Count];
                            bool paramsOk = true;
 
                            for (int i = 0; i < parameters.Length; i++) {
                                parameters[i] = DeserializeExpression(manager, null, objectCreateEx.Parameters[i]); 
                                if (parameters[i] is CodeExpression) { 

                                    // Before we bail on this parameter, see if the type is a delegate. 
                                    // If we are creating a delegate we may be able to bind to the method
                                    // after all.
                                    if (typeof(Delegate).IsAssignableFrom(type) && parameters.Length == 1 && parameters[i] is CodeMethodReferenceExpression) {
                                        CodeMethodReferenceExpression methodRef = (CodeMethodReferenceExpression)parameters[i]; 

                                        // Only do this if our target is not the root context. 
                                        if (!(methodRef.TargetObject is CodeThisReferenceExpression)) { 
                                            object target = DeserializeExpression(manager, null, methodRef.TargetObject);
                                            if (!(target is CodeExpression)) { 
                                                // Search for a matching method sig.  Must be public since we don't own this
                                                // object
                                                MethodInfo delegateInvoke = type.GetMethod("Invoke");
                                                if (delegateInvoke != null) { 
                                                    ParameterInfo[] delegateParams = delegateInvoke.GetParameters();
                                                    Type[] paramTypes = new Type[delegateParams.Length]; 
                                                    for (int idx = 0; idx < paramTypes.Length; idx++) { 
                                                        paramTypes[idx] = delegateParams[i].ParameterType;
                                                    } 
                                                    MethodInfo mi = TypeDescriptor.GetReflectionType(target).GetMethod(methodRef.MethodName, paramTypes);
                                                    if (mi != null) {
                                                        result = Activator.CreateInstance(type, new object[] { target, mi.MethodHandle.GetFunctionPointer() });
                                                    } 
                                                }
                                            } 
                                        } 
                                    }
 
                                    // Technically, the paramters are not OK.  Our special case above, if
                                    // successful, would have produced a "result" object for us.
                                    paramsOk = false;
                                    break; 
                                }
                            } 
 
                            if (paramsOk) {
                                // Create an instance of the object.  If the caller provided a name, 
                                // then ask the manager to add this object to the container.
                                result = DeserializeInstance(manager, type, parameters, name, (name != null));
                            }
                        } 
                        else {
                            TraceError("Type {0} could not be loaded", objectCreateEx.CreateType.BaseType); 
                            Error(manager, SR.GetString(SR.SerializerTypeNotFound, objectCreateEx.CreateType.BaseType), SR.SerializerTypeNotFound); 
                        }
 
                        break;
                    }
                    else if ((argumentReferenceEx = result as CodeArgumentReferenceExpression) != null) {
                        Trace("Named argument reference : {0}", argumentReferenceEx.ParameterName); 
                        result = manager.GetInstance(argumentReferenceEx.ParameterName);
                        if (result == null) { 
                            TraceError("Parameter {0} does not exist", argumentReferenceEx.ParameterName); 
                            Error(manager, SR.GetString(SR.SerializerUndeclaredName, argumentReferenceEx.ParameterName), SR.SerializerUndeclaredName);
                        } 

                        break;
                    }
                    else if ((fieldReferenceEx = result as CodeFieldReferenceExpression) != null) { 
                        Trace("Field reference : {0}", fieldReferenceEx.FieldName);
 
                        object target = DeserializeExpression(manager, null, fieldReferenceEx.TargetObject); 

                        if (target != null && !(target is CodeExpression)) { 
                            // If the target is the root object, then this won't be found
                            // through reflection.  Instead, ask the manager for the field
                            // by name.
                            // 
                            RootContext rootExp = (RootContext)manager.Context[typeof(RootContext)];
 
                            if (rootExp != null && rootExp.Value == target) { 
                                object namedObject = manager.GetInstance(fieldReferenceEx.FieldName);
 
                                if (namedObject != null) {
                                    result = namedObject;
                                }
                                else { 
                                    TraceError("Field {0} could not be resolved", fieldReferenceEx.FieldName);
                                    Error(manager, SR.GetString(SR.SerializerUndeclaredName, fieldReferenceEx.FieldName), SR.SerializerUndeclaredName); 
                                } 
                            }
                            else { 
                                FieldInfo field;
                                object instance;
                                Type t = target as Type;
 
                                if (t != null) {
                                    instance = null; 
                                    field = TypeDescriptor.GetReflectionType(t).GetField(fieldReferenceEx.FieldName, BindingFlags.GetField | BindingFlags.Static | BindingFlags.Public); 
                                }
                                else { 
                                    instance = target;
                                    field = TypeDescriptor.GetReflectionType(target).GetField(fieldReferenceEx.FieldName, BindingFlags.GetField | BindingFlags.Instance | BindingFlags.Public);
                                }
 
                                if (field != null) {
                                    result = field.GetValue(instance); 
                                } 
                                else {
                                    //lets try it as a property: 
                                    CodePropertyReferenceExpression propRef = new CodePropertyReferenceExpression();
                                    propRef.TargetObject = fieldReferenceEx.TargetObject;
                                    propRef.PropertyName = fieldReferenceEx.FieldName;
 
                                    result = DeserializePropertyReferenceExpression(manager, propRef, false);
                                    if (result == fieldReferenceEx) { 
                                        Error(manager, SR.GetString(SR.SerializerUndeclaredName, fieldReferenceEx.FieldName), SR.SerializerUndeclaredName); 
                                    }
                                } 
                            }
                        }
                        else {
                            Error(manager, SR.GetString(SR.SerializerFieldTargetEvalFailed, fieldReferenceEx.FieldName), SR.SerializerFieldTargetEvalFailed); 
                        }
 
                        TraceWarningIf(result == fieldReferenceEx, "Could not resolve field {0} to an object instance.", fieldReferenceEx.FieldName); 
                        break;
                    } 
                    else if ((methodInvokeEx = result as CodeMethodInvokeExpression) != null) {
                        Trace("Method invoke : {0}", methodInvokeEx.Method.MethodName);

                        object targetObject = DeserializeExpression(manager, null, methodInvokeEx.Method.TargetObject); 

                        if (targetObject != null) { 
                            object[] parameters = new object[methodInvokeEx.Parameters.Count]; 
                            bool paramsOk = true;
 
                            for (int i = 0; i < parameters.Length; i++) {
                                parameters[i] = DeserializeExpression(manager, null, methodInvokeEx.Parameters[i]);
                                if (parameters[i] is CodeExpression) {
                                    paramsOk = false; 
                                    break;
                                } 
                            } 

                            if (paramsOk) { 
                                IComponentChangeService compChange = (IComponentChangeService)manager.GetService(typeof(IComponentChangeService));
                                Type t = targetObject as Type;

                                if (t != null) { 
                                    result = TypeDescriptor.GetReflectionType(t).InvokeMember(methodInvokeEx.Method.MethodName, BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static, null, null, parameters, null, null, null);
                                } 
                                else { 
                                    if (compChange != null) {
                                        compChange.OnComponentChanging(targetObject, null); 
                                    }

                                    try {
                                        result = TypeDescriptor.GetReflectionType(targetObject).InvokeMember(methodInvokeEx.Method.MethodName, BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Instance, null, targetObject, parameters, null, null, null); 
                                    }
                                    catch (MissingMethodException) { 
                                        // We did not find the method directly. Let's see if we can find it 
                                        // as an private implemented interface name.
                                        // 
                                        CodeCastExpression castExpr = methodInvokeEx.Method.TargetObject as CodeCastExpression;

                                        if (castExpr != null) {
                                            Type castType = manager.GetType(GetTypeNameFromCodeTypeReference(manager, castExpr.TargetType)); 

                                            if (castType != null && castType.IsInterface) { 
                                                result = TypeDescriptor.GetReflectionType(castType).InvokeMember(methodInvokeEx.Method.MethodName, BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, null, targetObject, parameters, null, null, null); 
                                            }
                                            else { 
                                                throw;
                                            }
                                        }
                                        else { 
                                            throw;
                                        } 
                                    } 
                                    if (compChange != null) {
                                        compChange.OnComponentChanged(targetObject, null, null, null); 
                                    }
                                }
                            }
                            else if (parameters.Length == 1 && parameters[0] is CodeDelegateCreateExpression) { 
                                string methodName = methodInvokeEx.Method.MethodName;
 
                                if (methodName.StartsWith("add_")) { 
                                    methodName = methodName.Substring(4);
                                    DeserializeAttachEventStatement(manager, new CodeAttachEventStatement(methodInvokeEx.Method.TargetObject, methodName, (CodeExpression)parameters[0])); 
                                    result = null;
                                }
                            }
                        } 

                        break; 
                    } 
                    else if ((variableReferenceEx = result as CodeVariableReferenceExpression) != null) {
                        Trace("Variable reference : {0}", variableReferenceEx.VariableName); 
                        result = manager.GetInstance(variableReferenceEx.VariableName);
                        if (result == null) {
                            TraceError("Variable {0} does not exist", variableReferenceEx.VariableName);
                            Error(manager, SR.GetString(SR.SerializerUndeclaredName, variableReferenceEx.VariableName), SR.SerializerUndeclaredName); 
                        }
 
                        break; 
                    }
                    else if ((castEx = result as CodeCastExpression) != null) { 
                        Trace("Cast : {0}", castEx.TargetType.BaseType);
                        result = DeserializeExpression(manager, name, castEx.Expression);

                        IConvertible ic = result as IConvertible; 

                        if (ic != null) { 
                            Type targetType = manager.GetType(GetTypeNameFromCodeTypeReference(manager, castEx.TargetType)); 

                            if (targetType != null) { 
                                result = ic.ToType(targetType, null);
                            }
                        }
 
                        break;
                    } 
                    else if (result is CodeBaseReferenceExpression) { //(is -> as doesn't help here, since the cast is different) 
                        RootContext rootExp = (RootContext)manager.Context[typeof(RootContext)];
 
                        if (rootExp != null) {
                            result = rootExp.Value;
                        }
                        else { 
                            result = null;
                        } 
 
                        break;
                    } 
                    else if ((arrayCreateEx = result as CodeArrayCreateExpression) != null) {
                        Trace("Array create : {0}", arrayCreateEx.CreateType.BaseType);

                        Type arrayType = manager.GetType(GetTypeNameFromCodeTypeReference(manager, arrayCreateEx.CreateType)); 
                        Array array = null;
 
                        if (arrayType != null) { 
                            if (arrayCreateEx.Initializers.Count > 0) {
                                Trace("{0} initializers", arrayCreateEx.Initializers.Count); 

                                // Passed an array of initializers.  Use this
                                // to create the array.  Note that we use an
                                // ArrayList here and add elements as we create them. 
                                // It is possible that an element cannot be resolved.
                                // This is an error, but we do not want to tank the 
                                // entire array.  If we kicked out the entire statement, 
                                // a missing control would cause all controls on a form
                                // to vanish. 
                                ArrayList arrayList = new ArrayList(arrayCreateEx.Initializers.Count);

                                foreach (CodeExpression initializer in arrayCreateEx.Initializers) {
                                    try { 
                                        object o = DeserializeExpression(manager, null, initializer);
 
                                        if (!(o is CodeExpression)) { 
                                            if (!arrayType.IsInstanceOfType(o)) {
                                                o = Convert.ChangeType(o, arrayType, CultureInfo.InvariantCulture); 
                                            }

                                            arrayList.Add(o);
                                        } 
                                    }
                                    catch (Exception ex) { 
                                        manager.ReportError(ex); 
                                    }
                                } 

                                array = Array.CreateInstance(arrayType, arrayList.Count);
                                arrayList.CopyTo(array, 0);
                            } 
                            else if (arrayCreateEx.SizeExpression != null) {
                                object o = DeserializeExpression(manager, name, arrayCreateEx.SizeExpression); 
 
                                Debug.Assert(o is IConvertible, "Array size expression could not be resolved to IConvertible: " + (o == null ? "(null)" : o.GetType().Name));
 
                                IConvertible ic = o as IConvertible;

                                if (ic != null) {
                                    int size = ic.ToInt32(null); 

                                    Trace("Initialized with expression that simplified to {0}", size); 
                                    array = Array.CreateInstance(arrayType, size); 
                                }
                            } 
                            else {
                                Trace("Initialized with size {0}", arrayCreateEx.Size);
                                array = Array.CreateInstance(arrayType, arrayCreateEx.Size);
                            } 
                        }
                        else { 
                            TraceError("Type could not be resolved: {0}", arrayCreateEx.CreateType.BaseType); 
                            Error(manager, SR.GetString(SR.SerializerTypeNotFound, arrayCreateEx.CreateType.BaseType), SR.SerializerTypeNotFound);
                        } 

                        result = array;
                        if (result != null && name != null) {
                            manager.SetName(result, name); 
                        }
 
                        break; 
                    }
                    else if ((arrayIndexerEx = result as CodeArrayIndexerExpression) != null) { 
                        Trace("Array indexer");

                        // For this, assume in any error we return a null.  The only errors
                        // here should come from a mal-formed expression. 
                        //
                        result = null; 
 
                        Array array = DeserializeExpression(manager, name, arrayIndexerEx.TargetObject) as Array;
 
                        if (array != null) {
                            int[] indexes = new int[arrayIndexerEx.Indices.Count];

                            Trace("Dims: {0}", indexes.Length); 

                            bool indexesOK = true; 
 
                            // The indexes have to be of type int32.  If they're not, then
                            // we cannot assign to this array. 
                            //
                            for (int i = 0; i < indexes.Length; i++) {
                                IConvertible index = DeserializeExpression(manager, name, arrayIndexerEx.Indices[i]) as IConvertible;
 
                                if (index != null) {
                                    indexes[i] = index.ToInt32(null); 
                                    Trace("[{0}] == {1}", i, indexes[i]); 
                                }
                                else { 
                                    TraceWarning("Index {0} could not be converted to int.  Type: {1}", i, (index == null ? "(null)" : index.GetType().Name));
                                    indexesOK = false;
                                    break;
                                } 
                            }
 
                            if (indexesOK) { 
                                result = array.GetValue(indexes);
                            } 
                        }

                        break;
                    } 
                    else if ((binaryOperatorEx = result as CodeBinaryOperatorExpression) != null) {
                        Trace("Binary operator : {0}", binaryOperatorEx.Operator); 
 
                        object left = DeserializeExpression(manager, null, binaryOperatorEx.Left);
                        object right = DeserializeExpression(manager, null, binaryOperatorEx.Right); 

                        // We assign the result to an arbitrary value here in case the operation could
                        // not be performed.
                        // 
                        result = left;
 
                        IConvertible icLeft = left as IConvertible; 
                        IConvertible icRight = right as IConvertible;
 
                        if (icLeft != null && icRight != null) {
                            result = ExecuteBinaryExpression(icLeft, icRight, binaryOperatorEx.Operator);
                        }
                        else { 
                            TraceWarning("Could not simplify left and right binary operators to IConvertible.");
                        } 
 
                        break;
                    } 
                    else if ((delegateInvokeEx = result as CodeDelegateInvokeExpression) != null) {
                        Trace("Delegate invoke");

                        object targetObject = DeserializeExpression(manager, null, delegateInvokeEx.TargetObject); 
                        Delegate del = targetObject as Delegate;
 
                        if (del != null) { 
                            object[] parameters = new object[delegateInvokeEx.Parameters.Count];
                            bool paramsOk = true; 

                            for (int i = 0; i < parameters.Length; i++) {
                                parameters[i] = DeserializeExpression(manager, null, delegateInvokeEx.Parameters[i]);
                                if (parameters[i] is CodeExpression) { 
                                    paramsOk = false;
                                    break; 
                                } 
                            }
 
                            if (paramsOk) {
                                Trace("Invoking {0} with {1} parameters", targetObject.GetType().Name, parameters.Length);
                                del.DynamicInvoke(parameters);
                            } 
                        }
 
                        break; 
                    }
                    else if ((directionEx = result as CodeDirectionExpression) != null) { 
                        Trace("Direction operator");
                        result = DeserializeExpression(manager, name, directionEx.Expression);
                        break;
                    } 
                    else if ((indexerEx = result as CodeIndexerExpression) != null) {
                        Trace("Indexer"); 
 
                        // For this, assume in any error we return a null.  The only errors
                        // here should come from a mal-formed expression. 
                        //
                        result = null;

                        object targetObject = DeserializeExpression(manager, null, indexerEx.TargetObject); 

                        if (targetObject != null) { 
                            object[] indexes = new object[indexerEx.Indices.Count]; 

                            Trace("Indexes: {0}", indexes.Length); 

                            bool indexesOK = true;

                            for (int i = 0; i < indexes.Length; i++) { 
                                indexes[i] = DeserializeExpression(manager, null, indexerEx.Indices[i]);
                                if (indexes[i] is CodeExpression) { 
                                    TraceWarning("Index {0} could not be simplified to an object.", i); 
                                    indexesOK = false;
                                    break; 
                                }
                            }

                            if (indexesOK) { 
                                result = TypeDescriptor.GetReflectionType(targetObject).InvokeMember("Item", BindingFlags.GetProperty | BindingFlags.Public | BindingFlags.Instance, null, targetObject, indexes, null, null, null);
                            } 
                        } 

                        break; 
                    }
                    else if (result is CodeSnippetExpression) {
                        Trace("Snippet");
                        result = null; 
                        break;
                    } 
                    else if ((parameterDeclaration = result as CodeParameterDeclarationExpression) != null) { 
                        Trace("Parameter declaration");
                        result = manager.GetType(GetTypeNameFromCodeTypeReference(manager, parameterDeclaration.Type)); 
                        break;
                    }
                    else if ((typeOfExpression = result as CodeTypeOfExpression) != null) {
                        Trace("Typeof({0})", typeOfExpression.Type.BaseType); 

                        string type = GetTypeNameFromCodeTypeReference(manager, typeOfExpression.Type); 
 
                        // add the array ranks so we get the right type of this thing.
                        // 
                        for (int i = 0; i < typeOfExpression.Type.ArrayRank; i++) {
                            type += "[]";
                        }
 
                        result = manager.GetType(type);
                        if (result == null) { 
                            TraceError("Type could not be resolved: {0}", type); 
                            Error(manager, SR.GetString(SR.SerializerTypeNotFound, type), SR.SerializerTypeNotFound);
                        } 
                        break;
                    }
                    else if (result is CodeEventReferenceExpression || result is CodeMethodReferenceExpression || result is CodeDelegateCreateExpression) {
                        // These are all the expressions we know about, but 
                        // expect to return to the caller because we cannot
                        // simplify them. 
                        // 
                        break;
                    } 
                    else {
                        // All expression evaluation happens above.  This codepath
                        // indicates that we got some sort of junk in the evalualtor,
                        // or that someone assigned result to a value without 
                        // breaking out of the loop.
                        // 
                        Debug.Fail("Unrecognized expression type: " + result.GetType().Name); 
                        break;
                    } 
                }
            }

            return result; 
        }
 
        ///  
        /// 
        ///     This method will inspect all of the properties on the given object fitting the filter, and check for that 
        ///     property in a resource blob.  This is useful for deserializing properties that cannot be represented
        ///     in code, such as design-time properties.
        /// 
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2102:CatchNonClsCompliantExceptionsInGeneralHandlers")] 
        protected void DeserializePropertiesFromResources(IDesignerSerializationManager manager, object value, Attribute[] filter) {
            using (TraceScope("ComponentCodeDomSerializerBase::DeserializePropertiesFromResources")) { 
                // It is much faster to dig through the resources first, and then map these resources 
                // to properties than it is to filter properties at each turn.  Why?  Because filtering
                // properties requires a separate filter call for each object (because designers get a chance 
                // to filter, the cache is per-component), while resources are loaded once per
                // document.
                //
                IDictionaryEnumerator de = ResourceCodeDomSerializer.Default.GetMetadataEnumerator(manager); 

                if (de == null) { 
                    de = ResourceCodeDomSerializer.Default.GetEnumerator(manager, CultureInfo.InvariantCulture); 
                }
 
                if (de != null) {
                    string ourObjectName;
                    RootContext root = manager.Context[typeof(RootContext)] as RootContext;
 
                    if (root != null && root.Value == value) {
                        ourObjectName = "$this"; 
                    } 
                    else {
                        ourObjectName = manager.GetName(value); 
                    }

                    PropertyDescriptorCollection ourProperties = TypeDescriptor.GetProperties(value);
 
                    while (de.MoveNext()) {
                        object current = de.Current; 
                        string resourceName = de.Key as string; 

                        Debug.Assert(resourceName != null, "non-string keys in dictionary entry"); 

                        int dotIndex = resourceName.IndexOf('.');

                        if (dotIndex == -1) { 
                            continue;
                        } 
 
                        string objectName = resourceName.Substring(0, dotIndex);
 
                        // Skip now if this isn't a value for our object.
                        //
                        if (!objectName.Equals(ourObjectName)) {
                            continue; 
                        }
 
                        string propertyName = resourceName.Substring(dotIndex + 1); 

                        // Now locate the property by this name. 
                        //
                        PropertyDescriptor property = ourProperties[propertyName];

                        if (property == null) { 
                            continue;
                        } 
 
                        // This property must have matching attributes.
                        // 
                        bool passFilter = true;

                        if (filter != null) {
                            AttributeCollection propAttributes = property.Attributes; 

                            foreach (Attribute a in filter) { 
                                if (!propAttributes.Contains(a)) { 
                                    passFilter = false;
                                    break; 
                                }
                            }
                        }
 
                        // If this property passes inspection, then set it.
                        // 
                        if (passFilter) { 
                            object resourceObject = de.Value;
 
                            Trace("Resource: {0}, value: {1}", resourceName, (resourceObject == null ? "(null)" : resourceObject));
                            try {
                                property.SetValue(value, resourceObject);
                            } 
                            catch (Exception e) {
                                manager.ReportError(e); 
                            } 
                        }
                    } 
                }
            }
        }
 
        /// 
        ///  
        ///     This is a helper method that will deserialize a given statement.  It deserializes 
        ///     the statement by interpreting and executing the CodeDom statement.
        ///  
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2102:CatchNonClsCompliantExceptionsInGeneralHandlers")]
        protected void DeserializeStatement(IDesignerSerializationManager manager, CodeStatement statement) {
            using (TraceScope("CodeDomSerializerBase::DeserializeStatement")) {
                Trace("Statement : {0}", statement.GetType().Name); 

                // Push this statement onto the context stack.  This allows any serializers handling an expression 
                // to know what it was connected to. 
                //
                manager.Context.Push(statement); 
                try {
                    //Perf: is -> as changes, change ordering based on possibility of occurance
                    //Please excuse the bad formatting, but I think it is more readable this way than
                    //nested indenting. 
                    CodeAssignStatement cas = statement as CodeAssignStatement;
 
                    if (cas != null) { 
                        DeserializeAssignStatement(manager, cas);
                    } 
                    else {
                        CodeVariableDeclarationStatement cvds = statement as CodeVariableDeclarationStatement;

                        if (cvds != null) { 
                            DeserializeVariableDeclarationStatement(manager, cvds);
                        } 
                        else if (statement is CodeCommentStatement) { 
                            // do nothing for comments.  This just supresses the debug warning
                        } 
                        else {
                            CodeExpressionStatement ces = statement as CodeExpressionStatement;

                            if (ces != null) { 
                                DeserializeExpression(manager, null, ces.Expression);
                            } 
                            else { 
                                CodeMethodReturnStatement cmrs = statement as CodeMethodReturnStatement;
 
                                if (cmrs != null) {
                                    DeserializeExpression(manager, null, ces.Expression);
                                }
                                else { 
                                    CodeAttachEventStatement caes = statement as CodeAttachEventStatement;
 
                                    if (caes != null) { 
                                        DeserializeAttachEventStatement(manager, caes);
                                    } 
                                    else {
                                        CodeRemoveEventStatement cres = statement as CodeRemoveEventStatement;

                                        if (cres != null) { 
                                            DeserializeDetachEventStatement(manager, cres);
                                        } 
                                        else { 
                                            CodeLabeledStatement cls = statement as CodeLabeledStatement;
 
                                            if (cls != null) {
                                                DeserializeStatement(manager, cls.Statement);
                                            }
                                            else { 
                                                TraceWarning("Unrecognized statement type: {0}", statement.GetType().Name);
                                            } 
                                        } 
                                    }
                                } 
                            }
                        }
                    } // yes, these paranthesis are needed
                } 
                catch (CheckoutException) {
                    throw; // we want to propagate those all the way up 
                } 
                catch (Exception e) {
                    // Since we always go through reflection, don't 
                    // show what our engine does, show what caused
                    // the problem.
                    //
                    if (e is TargetInvocationException) { 
                        e = e.InnerException;
                    } 
 
                    if (!(e is CodeDomSerializerException) && statement.LinePragma != null) {
                        e = new CodeDomSerializerException(e, statement.LinePragma); 
                    }

                    manager.ReportError(e);
                } 
                finally {
                    Debug.Assert(manager.Context.Current == statement, "Someone corrupted the context stack"); 
                    manager.Context.Pop(); 
                }
            } 
        }

        private bool DeserializePropertyAssignStatement(IDesignerSerializationManager manager, CodeAssignStatement statement,
            CodePropertyReferenceExpression propertyReferenceEx, bool reportError) { 
            Trace("LHS is property : {0}", propertyReferenceEx.PropertyName);
 
            object lhs = DeserializeExpression(manager, null, propertyReferenceEx.TargetObject); 

            if (lhs != null && !(lhs is CodeExpression)) { 
                // Property assignments must go through our type descriptor system.
                // However, we do not support parameterized properties.  If there are
                // any parameters on the property, we do not perform the assignment.
                // 
                PropertyDescriptor p = TypeDescriptor.GetProperties(lhs, runTimeProperties)[propertyReferenceEx.PropertyName];
 
                if (p != null) { 
                    Trace("Processing RHS");
 
                    object rhs = DeserializeExpression(manager, null, statement.Right);

                    if (rhs is CodeExpression) {
                        TraceError("Unable to simplify statement to anything better than: {0}", rhs.GetType().Name); 
                        return false;
                    } 
 
                    IConvertible ic = rhs as IConvertible;
 
                    if (ic != null && p.PropertyType != rhs.GetType()) {
                        try {
                            rhs = ic.ToType(p.PropertyType, null);
                        } 
                        catch {
                            // oh well... 
                        } 
                    }
 
                    //VSWhidbey#580599 We need to ensure that no virtual types leak into the runtime code
                    //So if we ever assign a property value to a Type -- we make sure that the Type is a
                    // real System.Type.
                    Type rhsType = rhs as Type; 
                    if (rhsType != null && rhsType.UnderlyingSystemType != null)
                    { 
                        rhs = rhsType.UnderlyingSystemType; //unwrap this "type" that came because it was not actually a real bcl type. 
                    }
 
                    // Next: see if the RHS of this expression was a property reference too.  If it was, then
                    // we will look for a MemberRelationshipService to record the relationship between these
                    // two properties, if supported.
 
                    // VSWhidbey 504238.
                    // We need to setup this MemberRelationship before we actually set the property value. 
                    // If we do it the other way around the new property value will be pushed into the old 
                    // relationship, which isn't a problem during normal serialization (since it not very
                    // likely the property has already been assigned to), but it does affect undo. 
                    MemberRelationship oldRelation = MemberRelationship.Empty;
                    MemberRelationshipService relationships = null;
                    if (statement.Right is CodePropertyReferenceExpression) {
                        relationships = manager.GetService(typeof(MemberRelationshipService)) as MemberRelationshipService; 

                        if (relationships != null) { 
                            CodePropertyReferenceExpression rhsPropRef = (CodePropertyReferenceExpression)statement.Right; 
                            object rhsPropTarget = DeserializeExpression(manager, null, rhsPropRef.TargetObject);
                            PropertyDescriptor rhsProp = TypeDescriptor.GetProperties(rhsPropTarget)[rhsPropRef.PropertyName]; 

                            if (rhsProp != null) {
                                MemberRelationship source = new MemberRelationship(lhs, p);
                                MemberRelationship target = new MemberRelationship(rhsPropTarget, rhsProp); 

                                oldRelation = relationships[source]; 
 
                                if (relationships.SupportsRelationship(source, target)) {
                                    relationships[source] = target; 
                                }
                            }
                        }
                    } 
                    else {
                        relationships = manager.GetService(typeof(MemberRelationshipService)) as MemberRelationshipService; 
 
                        if (relationships != null) {
                            oldRelation = relationships[lhs, p]; 
                            relationships[lhs, p] = MemberRelationship.Empty;
                        }
                    }
 
                    try {
                        p.SetValue(lhs, rhs); 
                    } 
                    catch {
                        if (relationships != null) { 
                            relationships[lhs, p] = oldRelation;
                        }
                        throw;
                    } 
                    return true;
                } 
                else { 
                    if (reportError) {
                        TraceError("Object {0} does not have a property {1}", lhs.GetType().Name, propertyReferenceEx.PropertyName); 
                        Error(manager, SR.GetString(SR.SerializerNoSuchProperty, lhs.GetType().FullName, propertyReferenceEx.PropertyName), SR.SerializerNoSuchProperty);
                    }
                }
            } 
            else {
                TraceWarning("Could not find target object for property {0}", propertyReferenceEx.PropertyName); 
            } 
            return false;
        } 

        /// 
        /// 
        ///     Deserializes an assign statement by performing the assignment. 
        /// 
        private void DeserializeAssignStatement(IDesignerSerializationManager manager, CodeAssignStatement statement) { 
            using (TraceScope("CodeDomSerializerBase::DeserializeAssignStatement")) { 
                // Since we're doing an assignment into something, we need to know
                // what that something is.  It can be a property, a variable, or 
                // a member. Anything else is invalid.
                //
                //Perf: is -> as changes, change ordering based on possibility of occurance
                CodeExpression expression = statement.Left; 
                CodePropertyReferenceExpression propertyReferenceEx;
                CodeFieldReferenceExpression fieldReferenceEx; 
                CodeVariableReferenceExpression variableReferenceEx; 
                CodeArrayIndexerExpression arrayIndexerEx;
 
                Trace("Processing LHS");
                if ((propertyReferenceEx = expression as CodePropertyReferenceExpression) != null) {
                    DeserializePropertyAssignStatement(manager, statement, propertyReferenceEx, true);
                } 
                else if ((fieldReferenceEx = expression as CodeFieldReferenceExpression) != null) {
                    Trace("LHS is field : {0}", fieldReferenceEx.FieldName); 
 
                    object lhs = DeserializeExpression(manager, fieldReferenceEx.FieldName, fieldReferenceEx.TargetObject);
 
                    if (lhs != null) {
                        RootContext root = (RootContext)manager.Context[typeof(RootContext)];

                        if (root != null && root.Value == lhs) { 
                            Trace("Processing RHS");
 
                            object rhs = DeserializeExpression(manager, fieldReferenceEx.FieldName, statement.Right); 

                            if (rhs is CodeExpression) { 
                                TraceError("Unable to simplify statement to anything better than: {0}", rhs.GetType().Name);
                                return;
                            }
                        } 
                        else {
                            FieldInfo f; 
                            object instance; 
                            Type type = lhs as Type;
 
                            if (type != null) {
                                instance = null;
                                f = TypeDescriptor.GetReflectionType(type).GetField(fieldReferenceEx.FieldName, BindingFlags.GetField | BindingFlags.Static | BindingFlags.Public);
                            } 
                            else {
                                instance = lhs; 
                                f = TypeDescriptor.GetReflectionType(lhs).GetField(fieldReferenceEx.FieldName, BindingFlags.GetField | BindingFlags.Instance | BindingFlags.Public); 
                            }
 
                            if (f != null) {
                                Trace("Processing RHS");

                                object rhs = DeserializeExpression(manager, fieldReferenceEx.FieldName, statement.Right); 

                                if (rhs is CodeExpression) { 
                                    TraceError("Unable to simplify statement to anything better than: {0}", rhs.GetType().Name); 
                                    return;
                                } 

                                IConvertible ic = rhs as IConvertible;

                                if (ic != null && f.FieldType != rhs.GetType()) { 
                                    try {
                                        rhs = ic.ToType(f.FieldType, null); 
                                    } 
                                    catch {
                                        // oh well... 
                                    }
                                }

                                f.SetValue(instance, rhs); 
                            }
                            else { 
                                //lets try it as a property: 
                                CodePropertyReferenceExpression propRef = new CodePropertyReferenceExpression();
                                propRef.TargetObject = fieldReferenceEx.TargetObject; 
                                propRef.PropertyName = fieldReferenceEx.FieldName;

                                if (!DeserializePropertyAssignStatement(manager, statement, propRef, false)) {
                                    TraceError("Object {0} does not have a field {1}", lhs.GetType().Name, fieldReferenceEx.FieldName); 
                                    Error(manager, SR.GetString(SR.SerializerNoSuchField, lhs.GetType().FullName, fieldReferenceEx.FieldName), SR.SerializerNoSuchField);
                                } 
                            } 
                        }
                    } 
                    else {
                        TraceWarning("Could not find target object for field {0}", fieldReferenceEx.FieldName);
                    }
                } 
                else if ((variableReferenceEx = expression as CodeVariableReferenceExpression) != null) {
                    // This is the easiest.  Just relate the RHS object to the name of the variable. 
                    // 
                    Trace("Processing RHS");
 
                    object rhs = DeserializeExpression(manager, variableReferenceEx.VariableName, statement.Right);

                    if (rhs is CodeExpression) {
                        TraceError("Unable to simplify statement to anything better than: {0}", rhs.GetType().Name); 
                        return;
                    } 
 
                    manager.SetName(rhs, variableReferenceEx.VariableName);
                } 
                else if ((arrayIndexerEx = expression as CodeArrayIndexerExpression) != null) {
                    int[] indexes = new int[arrayIndexerEx.Indices.Count];

                    Trace("LHS is Array Indexer with dims {0}", indexes.Length); 

                    object array = DeserializeExpression(manager, null, arrayIndexerEx.TargetObject); 
                    bool indexesOK = true; 

                    // The indexes have to be of type int32.  If they're not, then 
                    // we cannot assign to this array.
                    //
                    for (int i = 0; i < indexes.Length; i++) {
                        object index = DeserializeExpression(manager, null, arrayIndexerEx.Indices[i]); 
                        IConvertible ic = index as IConvertible;
 
                        if (ic != null) { 
                            indexes[i] = ic.ToInt32(null);
                            Trace("[{0}] == {1}", i, indexes[i]); 
                        }
                        else {
                            TraceWarning("Index {0} could not be converted to int.  Type: {1}", i, (index == null ? "(null)" : index.GetType().Name));
                            indexesOK = false; 
                            break;
                        } 
                    } 

                    Array arr = array as Array; 

                    if (arr != null && indexesOK) {
                        Trace("Processing RHS");
 
                        object rhs = DeserializeExpression(manager, null, statement.Right);
 
                        if (rhs is CodeExpression) { 
                            TraceError("Unable to simplify statement to anything better than: {0}", rhs.GetType().Name);
                            return; 
                        }

                        arr.SetValue(rhs, indexes);
                    } 
                    else {
                        TraceErrorIf(!(array is Array), "Array resovled to something other than an array: {0}", (array == null ? "(null)" : array.GetType().Name)); 
                        TraceErrorIf(!indexesOK, "Indexes to array could not be converted to int32."); 
                    }
                } 
            }
        }

        ///  
        /// 
        ///     Deserializes the event attachment by setting the event value throught IEventBindingService. 
        ///  
        private void DeserializeAttachEventStatement(IDesignerSerializationManager manager, CodeAttachEventStatement statement) {
            using (TraceScope("CodeDomSerializerBase::DeserializeAttachEventStatement")) { 
                string handlerMethodName = null;
                object eventAttachObject = null;

                // Get the target information 
                //
                object targetObject = DeserializeExpression(manager, null, statement.Event.TargetObject); 
                string eventName = statement.Event.EventName; 

                Debug.Assert(targetObject != null, "Failed to get target object for event attach"); 
                Debug.Assert(eventName != null, "Failed to get eventName for event attach");
                if (eventName == null || targetObject == null) {
                    return;
                } 

                CodeObjectCreateExpression objCreate = statement.Listener as CodeObjectCreateExpression; 
 
                if (objCreate != null) {
                    // now walk into the CodeObjectCreateExpression and get the parameters so we can 
                    // get the name of the method, e.g. button1_Click
                    //
                    if (objCreate.Parameters.Count == 1) {
                        // if this is a delegate create (new EventHandler(this.button1_Click)), then 
                        // the first parameter should be a method ref.
                        // 
                        CodeMethodReferenceExpression methodRef = objCreate.Parameters[0] as CodeMethodReferenceExpression; 

                        if (methodRef != null) { 
                            handlerMethodName = methodRef.MethodName;
                            eventAttachObject = DeserializeExpression(manager, null, methodRef.TargetObject);
                        }
                    } 
                    else {
                        Debug.Fail("Encountered delegate object create with more or less than 1 parameter?"); 
                    } 
                }
                else { 
                    object eventListener = DeserializeExpression(manager, null, statement.Listener);
                    CodeDelegateCreateExpression delegateCreate = eventListener as CodeDelegateCreateExpression;

                    if (delegateCreate != null) { 
                        eventAttachObject = DeserializeExpression(manager, null, delegateCreate.TargetObject);
                        handlerMethodName = delegateCreate.MethodName; 
                    } 
                }
 
                RootContext rootExp = (RootContext)manager.Context[typeof(RootContext)];
                bool isRoot = rootExp == null || (rootExp != null && rootExp.Value == eventAttachObject);

                if (handlerMethodName == null) { 
                    TraceError("Unable to retrieve handler method and object for delegate create.");
                } 
                else { 
                    // We only support binding methods to the root object.
                    // 
                    TraceWarningIf(!isRoot, "Event is bound to an object other than the root.  We do not support this.");
                    if (isRoot) {
                        // Now deserialize the LHS of the event attach to discover the guy whose
                        // event we are attaching. 
                        //
                        TraceErrorIf(targetObject is CodeExpression, "Unable to simplify event attach LHS to an object reference."); 
                        if (!(targetObject is CodeExpression)) { 
                            EventDescriptor evt = TypeDescriptor.GetEvents(targetObject)[eventName];
 
                            if (evt != null) {
                                IEventBindingService evtSvc = (IEventBindingService)manager.GetService(typeof(IEventBindingService));

                                if (evtSvc != null) { 
                                    PropertyDescriptor prop = evtSvc.GetEventProperty(evt);
 
                                    prop.SetValue(targetObject, handlerMethodName); 
                                    Trace("Attached event {0}.{1} to {2}", targetObject.GetType().Name, eventName, handlerMethodName);
                                } 
                            }
                            else {
                                TraceError("Object {0} does not have a event {1}", targetObject.GetType().Name, eventName);
                                Error(manager, SR.GetString(SR.SerializerNoSuchEvent, targetObject.GetType().FullName, eventName), SR.SerializerNoSuchEvent); 
                            }
                        } 
                    } 
                }
            } 
        }

        /// 
        ///  
        ///     Deserializes the event detachment by setting the event value throught IEventBindingService.
        ///  
        private void DeserializeDetachEventStatement(IDesignerSerializationManager manager, CodeRemoveEventStatement statement) { 
            using (TraceScope("CodeDomSerializerBase::DeserializeDetachEventStatement")) {
                object eventListener = DeserializeExpression(manager, null, statement.Listener); 

                TraceErrorIf(!(eventListener is CodeDelegateCreateExpression), "Unable to simplify event attach RHS to a delegate create.");

                CodeDelegateCreateExpression delegateCreate = eventListener as CodeDelegateCreateExpression; 

                if (delegateCreate != null) { 
                    // We only support binding methods to the root object. 
                    //
                    object eventAttachObject = DeserializeExpression(manager, null, delegateCreate.TargetObject); 
                    RootContext rootExp = (RootContext)manager.Context[typeof(RootContext)];
                    bool isRoot = rootExp == null || (rootExp != null && rootExp.Value == eventAttachObject);

                    TraceWarningIf(!isRoot, "Event is bound to an object other than the root.  We do not support this."); 
                    if (isRoot) {
                        // Now deserialize the LHS of the event attach to discover the guy whose 
                        // event we are attaching. 
                        //
                        object targetObject = DeserializeExpression(manager, null, statement.Event.TargetObject); 

                        TraceErrorIf(targetObject is CodeExpression, "Unable to simplify event attach LHS to an object reference.");
                        if (!(targetObject is CodeExpression)) {
                            EventDescriptor evt = TypeDescriptor.GetEvents(targetObject)[statement.Event.EventName]; 

                            if (evt != null) { 
                                IEventBindingService evtSvc = (IEventBindingService)manager.GetService(typeof(IEventBindingService)); 

                                if (evtSvc != null) { 
                                    PropertyDescriptor prop = evtSvc.GetEventProperty(evt);

                                    prop.SetValue(targetObject, null);
                                } 
                            }
                            else { 
                                TraceError("Object {0} does not have a event {1}", targetObject.GetType().Name, statement.Event.EventName); 
                                Error(manager, SR.GetString(SR.SerializerNoSuchEvent, targetObject.GetType().FullName, statement.Event.EventName), SR.SerializerNoSuchEvent);
                            } 
                        }
                    }
                }
            } 
        }
 
        ///  
        /// 
        ///     Deserializes a variable declaration by deserializing the target object of the variable and providing a name. 
        /// 
        private void DeserializeVariableDeclarationStatement(IDesignerSerializationManager manager, CodeVariableDeclarationStatement statement) {
            using (TraceScope("CodeDomSerializerBase::DeserializeVariableDeclarationStatement")) {
                if (statement.InitExpression != null) { 
                    Trace("Processing init expression");
                    DeserializeExpression(manager, statement.Name, statement.InitExpression); 
                } 
            }
        } 

        /// 
        /// 
        ///     This creates a new exception object with the given string.  It attempts to discover the 
        ///     current statement, and if it can find one, will create a CodeDomSerializerException that
        ///     contains the correct file / line number information.  After creating the exception, it 
        ///     throws it. 
        /// 
        internal void Error(IDesignerSerializationManager manager, string exceptionText, string helpLink) { 
            if (manager == null) throw new ArgumentNullException("manager");
            if (exceptionText == null) throw new ArgumentNullException("exceptionText");

            CodeStatement statement = (CodeStatement)manager.Context[typeof(CodeStatement)]; 
            CodeLinePragma linePragma = null;
 
            if (statement != null) { 
                linePragma = statement.LinePragma;
            } 

            Exception exception = new CodeDomSerializerException(exceptionText, linePragma);
            exception.HelpLink = helpLink;
            throw exception; 
        }
 
        ///  
        /// 
        ///     Executes the given binary expression.  If at any stage of the game the expression execution fails, 
        ///     this just returns the default value for the datatype required by the operator.  Boolean == false,
        ///     for example.
        /// 
        private object ExecuteBinaryExpression(IConvertible left, IConvertible right, CodeBinaryOperatorType op) { 

            // "Binary" operator type is actually a combination of several types of operators: boolean, binary 
            //  and math.  Group them into categories here. 
            //
            CodeBinaryOperatorType[] booleanOperators = new CodeBinaryOperatorType[] { 
                CodeBinaryOperatorType.IdentityInequality,
                CodeBinaryOperatorType.IdentityEquality,
                CodeBinaryOperatorType.ValueEquality,
                CodeBinaryOperatorType.BooleanOr, 
                CodeBinaryOperatorType.BooleanAnd,
                CodeBinaryOperatorType.LessThan, 
                CodeBinaryOperatorType.LessThanOrEqual, 
                CodeBinaryOperatorType.GreaterThan,
                CodeBinaryOperatorType.GreaterThanOrEqual 
            };

            CodeBinaryOperatorType[] mathOperators = new CodeBinaryOperatorType[] {
                CodeBinaryOperatorType.Add, 
                CodeBinaryOperatorType.Subtract,
                CodeBinaryOperatorType.Multiply, 
                CodeBinaryOperatorType.Divide, 
                CodeBinaryOperatorType.Modulus
            }; 

            CodeBinaryOperatorType[] binaryOperators = new CodeBinaryOperatorType[] {
                CodeBinaryOperatorType.BitwiseOr,
                CodeBinaryOperatorType.BitwiseAnd 
            };
 
            // Figure out what kind of expression we have. 
            //
            for (int i = 0; i < binaryOperators.Length; i++) { 
                if (op == binaryOperators[i]) {
                    return ExecuteBinaryOperator(left, right, op);
                }
            } 
            for (int i = 0; i < mathOperators.Length; i++) {
                if (op == mathOperators[i]) { 
                    return ExecuteMathOperator(left, right, op); 
                }
            } 
            for (int i = 0; i < booleanOperators.Length; i++) {
                if (op == booleanOperators[i]) {
                    return ExecuteBooleanOperator(left, right, op);
                } 
            }
 
            Debug.Fail("Unsupported binary operator type: " + op.ToString()); 
            return left;
        } 

        /// 
        /// 
        ///     Executes the given binary operator.  If at any stage of the game the expression execution fails, 
        ///     this just returns the left hand side.
        ///     for example. 
        ///  
        private object ExecuteBinaryOperator(IConvertible left, IConvertible right, CodeBinaryOperatorType op) {
            TypeCode leftType = left.GetTypeCode(); 
            TypeCode rightType = right.GetTypeCode();

            // The compatible types are listed in order from lowest bitness to highest.  We must
            // operate on the highest bitness to keep fidelity. 
            //
            TypeCode[] compatibleTypes = new TypeCode[] { 
                TypeCode.Byte, 
                TypeCode.Char,
                TypeCode.Int16, 
                TypeCode.UInt16,
                TypeCode.Int32,
                TypeCode.UInt32,
                TypeCode.Int64, 
                TypeCode.UInt64};
 
            int leftTypeIndex = -1; 
            int rightTypeIndex = -1;
 
            for (int i = 0; i < compatibleTypes.Length; i++) {
                if (leftType == compatibleTypes[i]) {
                    leftTypeIndex = i;
                } 
                if (rightType == compatibleTypes[i]) {
                    rightTypeIndex = i; 
                } 
                if (leftTypeIndex != -1 && rightTypeIndex != -1) {
                    break; 
                }
            }

            if (leftTypeIndex == -1 || rightTypeIndex == -1) { 
                Debug.Fail("Could not convert left or right side to binary-compatible value.");
                return left; 
            } 

            int maxIndex = Math.Max(leftTypeIndex, rightTypeIndex); 
            object result = left;

            switch (compatibleTypes[maxIndex]) {
                case TypeCode.Byte: { 
                        byte leftValue = left.ToByte(null);
                        byte rightValue = right.ToByte(null); 
 
                        if (op == CodeBinaryOperatorType.BitwiseOr) {
                            result = leftValue | rightValue; 
                        }
                        else {
                            result = leftValue & rightValue;
                        } 
                        break;
                    } 
                case TypeCode.Char: { 
                        char leftValue = left.ToChar(null);
                        char rightValue = right.ToChar(null); 

                        if (op == CodeBinaryOperatorType.BitwiseOr) {
                            result = leftValue | rightValue;
                        } 
                        else {
                            result = leftValue & rightValue; 
                        } 
                        break;
                    } 
                case TypeCode.Int16: {
                        short leftValue = left.ToInt16(null);
                        short rightValue = right.ToInt16(null);
 
                        if (op == CodeBinaryOperatorType.BitwiseOr) {
                            result = (short)((ushort)leftValue | (ushort)rightValue); 
                        } 
                        else {
                            result = leftValue & rightValue; 
                        }
                        break;
                    }
                case TypeCode.UInt16: { 
                        ushort leftValue = left.ToUInt16(null);
                        ushort rightValue = right.ToUInt16(null); 
 
                        if (op == CodeBinaryOperatorType.BitwiseOr) {
                            result = leftValue | rightValue; 
                        }
                        else {
                            result = leftValue & rightValue;
                        } 
                        break;
                    } 
                case TypeCode.Int32: { 
                        int leftValue = left.ToInt32(null);
                        int rightValue = right.ToInt32(null); 

                        if (op == CodeBinaryOperatorType.BitwiseOr) {
                            result = leftValue | rightValue;
                        } 
                        else {
                            result = leftValue & rightValue; 
                        } 
                        break;
                    } 
                case TypeCode.UInt32: {
                        uint leftValue = left.ToUInt32(null);
                        uint rightValue = right.ToUInt32(null);
 
                        if (op == CodeBinaryOperatorType.BitwiseOr) {
                            result = leftValue | rightValue; 
                        } 
                        else {
                            result = leftValue & rightValue; 
                        }
                        break;
                    }
                case TypeCode.Int64: { 
                        long leftValue = left.ToInt64(null);
                        long rightValue = right.ToInt64(null); 
 
                        if (op == CodeBinaryOperatorType.BitwiseOr) {
                            result = leftValue | rightValue; 
                        }
                        else {
                            result = leftValue & rightValue;
                        } 
                        break;
                    } 
                case TypeCode.UInt64: { 
                        ulong leftValue = left.ToUInt64(null);
                        ulong rightValue = right.ToUInt64(null); 

                        if (op == CodeBinaryOperatorType.BitwiseOr) {
                            result = leftValue | rightValue;
                        } 
                        else {
                            result = leftValue & rightValue; 
                        } 
                        break;
                    } 
            }

            if (result != left && left is Enum) {
                // For enums, try to convert back to the original type 
                //
                result = Enum.ToObject(left.GetType(), result); 
            } 
            return result;
        } 

        /// 
        /// 
        ///     Executes the given boolean operator.  If at any stage of the game the expression execution fails, 
        ///     this just returns false.
        ///     for example. 
        ///  
        private object ExecuteBooleanOperator(IConvertible left, IConvertible right, CodeBinaryOperatorType op) {
            bool result = false; 

            switch (op) {
                case CodeBinaryOperatorType.IdentityInequality:
                    result = (left != right); 
                    break;
                case CodeBinaryOperatorType.IdentityEquality: 
                    result = (left == right); 
                    break;
                case CodeBinaryOperatorType.ValueEquality: 
                    result = left.Equals(right);
                    break;
                case CodeBinaryOperatorType.BooleanOr:
                    result = (left.ToBoolean(null) || right.ToBoolean(null)); 
                    break;
                case CodeBinaryOperatorType.BooleanAnd: 
                    result = (left.ToBoolean(null) && right.ToBoolean(null)); 
                    break;
                case CodeBinaryOperatorType.LessThan: 
                    // Not doing these at design time.
                    break;
                case CodeBinaryOperatorType.LessThanOrEqual:
                    // Not doing these at design time. 
                    break;
                case CodeBinaryOperatorType.GreaterThan: 
                    // Not doing these at design time. 
                    break;
                case CodeBinaryOperatorType.GreaterThanOrEqual: 
                    // Not doing these at design time.
                    break;
                default:
                    Debug.Fail("Should never get here!"); 
                    break;
            } 
 
            return result;
        } 

        /// 
        /// 
        ///     Executes the given math operator.  If at any stage of the game the expression execution fails, 
        ///     this just returns the left hand side.
        ///     for example. 
        ///  
        private object ExecuteMathOperator(IConvertible left, IConvertible right, CodeBinaryOperatorType op) {
 
            switch (op) {
                case CodeBinaryOperatorType.Add:
                    string leftString = left as string;
                    string rightString = right as string; 

                    if (leftString == null && left is Char) { 
                        leftString = left.ToString(); 
                    }
 
                    if (rightString == null && right is Char) {
                        rightString = right.ToString();
                    }
 
                    if (leftString != null && rightString != null) {
                        return leftString + rightString; 
                    } 
                    else {
                        Debug.Fail("Addition operator not supported for this type"); 
                        return left;
                    }
                default:
                    Debug.Fail("Math operators are not supported"); 
                    return left;
            } 
        } 

        ///  
        /// 
        ///    This method returns an expression representing the given object.  It may return null, indicating that
        ///    no expression has been set that describes the object.  Expressions are aquired in one of three ways:
        /// 
        ///    1.   The expression could be the result of a prior SetExpression call.
        ///    2.   The expression could have been found in the RootContext. 
        ///    3.   The expression could be derived through IReferenceService. 
        ///    4.   The current expression on the context stack has a PresetValue == value.
        /// 
        ///    To derive expressions through IReferenceService, GetExpression asks the reference service if there
        ///    is a name for the given object.  If the expression service returns a valid name, it checks to see if
        ///    there is a '.' in the name.  This indicates that the expression service found this object as the return
        ///    value of a read only property on another object.  If there is a '.', GetExpression will split the reference 
        ///    into sub-parts.  The leftmost part is a name that will be evalulated via manager.GetInstance.  For each
        ///    subsequent part, a property reference expression will be built.  The final expression will then be returned. 
        /// 
        ///    If the object did not have an expression set, or the object was not found in the reference service, null will
        ///    be returned from GetExpression, indicating there is no existing expression for the object. 
        /// 
        protected CodeExpression GetExpression(IDesignerSerializationManager manager, object value) {
            CodeExpression expression = null;
 
            if (manager == null) {
                throw new ArgumentNullException("manager"); 
            } 

            if (value == null) { 
                throw new ArgumentNullException("value");
            }

            Trace("GetExpression called for object {0}", value.ToString()); 

            // Is the expression part of a prior SetExpression call? 
            ExpressionTable table = manager.Context[typeof(ExpressionTable)] as ExpressionTable; 

            if (table != null) { 
                expression = table.GetExpression(value);
                TraceIf(expression != null, "Resolved through expression table : {0}", expression);
            }
 
            // Check to see if this object represents the root context.
            if (expression == null) { 
                RootContext rootEx = manager.Context[typeof(RootContext)] as RootContext; 

                if (rootEx != null && object.ReferenceEquals(rootEx.Value, value)) { 
                    expression = rootEx.Expression;
                    TraceIf(expression != null, "Resolved through root expression context : {0}", expression);
                }
            } 

            // Now check IReferenceService. 
            if (expression == null) { 

             // perf: first try to retrieve objectName from DesignerSerializationManager 
             // only then involve reference service if needed
             // this is done to avoid unnecessary ensuring\creating references

                string objectName = manager.GetName(value); 
                if (objectName == null || objectName.IndexOf('.') != -1)
                { 
                    IReferenceService refSvc = manager.GetService(typeof(IReferenceService)) as IReferenceService; 
                    if (refSvc != null)
                    { 
                        objectName = refSvc.GetName(value);
                        if (objectName != null && objectName.IndexOf('.') != -1)
                        {
                            Trace("Resolving through IReferenceService : {0}", objectName); 

                            // This object name is built from sub objects.  Assemble the graph of sub objects. 
                            string[] nameParts = objectName.Split('.'); 

                            Debug.Assert(nameParts.Length > 0, "How can we fail to split when IndexOf succeeded?"); 

                            object baseInstance = manager.GetInstance(nameParts[0]);

                            TraceWarningIf(baseInstance == null, "Manager can't return an instance for object {0}", nameParts[0]); 
                            if (baseInstance != null)
                            { 
                                CodeExpression baseExpression = SerializeToExpression(manager, baseInstance); 

                                TraceWarningIf(baseExpression == null, "Unable to serialize object {0} to an expression.", baseInstance); 
                                if (baseExpression != null)
                                {
                                    for (int idx = 1; idx < nameParts.Length; idx++)
                                    { 
                                        baseExpression = new CodePropertyReferenceExpression(baseExpression, nameParts[idx]);
                                    } 
 
                                    expression = baseExpression;
                                } 
                            }
                        }
                    }
                } 
            }
 
            // Finally, the expression context. 
            if (expression == null) {
                ExpressionContext cxt = manager.Context[typeof(ExpressionContext)] as ExpressionContext; 
                if (cxt != null && object.ReferenceEquals(cxt.PresetValue, value)) {
                    expression = cxt.Expression;
                }
            } 

            if (expression != null) { 
                // set up cache dependencies 
                // we check to see if there is anything on the stack
                // if there is we make the parent entry a dependency of the current entry 
                ComponentCache.Entry parentEntry = (ComponentCache.Entry)manager.Context[typeof(ComponentCache.Entry)];
                ComponentCache cache = (ComponentCache)manager.Context[typeof(ComponentCache)];

                if (parentEntry != null && parentEntry.Component != value /* don't make ourselves dependent with ourselves */ && cache != null) { 
                    ComponentCache.Entry entry = null;
                    entry = cache.GetEntryAll(value); 
                    if (entry != null && parentEntry.Component != null) { 
                        entry.AddDependency(parentEntry.Component);
                    } 
                }
            }

            return expression; 
        }
 
        // undone : we need this for backwards compat with the serializaiton code in M.VS.dll. Rip this when we rip that code. 
        private PropertyDescriptorCollection GetFilteredProperties(IDesignerSerializationManager manager, object value, Attribute[] filter) {
 
            IComponent comp = value as IComponent;

            PropertyDescriptorCollection props = TypeDescriptor.GetProperties(value, filter);
            if (comp != null) { 

                if (((IDictionary)props).IsReadOnly) { 
                    PropertyDescriptor[] propArray = new PropertyDescriptor[props.Count]; 
                    props.CopyTo(propArray, 0);
                    props = new PropertyDescriptorCollection(propArray); 
                }

                PropertyDescriptor filterProp = manager.Properties["FilteredProperties"];
 
                if (filterProp != null) {
                    ITypeDescriptorFilterService filterSvc = filterProp.GetValue(manager) as ITypeDescriptorFilterService; 
                    if (filterSvc != null) { 
                        filterSvc.FilterProperties(comp, props);
                    } 
                }
            }
            return props;
        } 

        private CodeExpression GetLegacyExpression(IDesignerSerializationManager manager, object value) { 
            LegacyExpressionTable table = manager.Context[typeof(LegacyExpressionTable)] as LegacyExpressionTable; 
            CodeExpression expression = null;
 
            if (table != null) {
                object exp = table[value];
                if (exp == value) {
                    // Sentinel.  Compute an actual legacy expression to store. 

                    string name = manager.GetName(value); 
                    bool referenceName = false; 

                    if (name == null) { 
                        IReferenceService referenceService = (IReferenceService)manager.GetService(typeof(IReferenceService));

                        if (referenceService != null) {
                            name = referenceService.GetName(value); 
                            referenceName = name != null;
                        } 
                    } 

                    if (name != null) { 
                        Trace("Object is reference ({0}) Creating reference expression", name);

                        // Check to see if this is a reference to the root component.  If it is, then use "this".
                        // 
                        RootContext root = (RootContext)manager.Context[typeof(RootContext)];
 
                        if (root != null) { 
                            if (root.Value == value) {
                                expression = root.Expression; 
                            }
                            else if (referenceName && name.IndexOf('.') != -1) {
                                // if it's a reference name with a dot, we've actually got a property here...
                                // 
                                int dotIndex = name.IndexOf('.');
 
                                expression = new CodePropertyReferenceExpression(new CodeFieldReferenceExpression(root.Expression, name.Substring(0, dotIndex)), name.Substring(dotIndex + 1)); 
                            }
                            else { 
                                expression = new CodeFieldReferenceExpression(root.Expression, name);
                            }
                        }
                        else { 
                            // A variable reference
                            if (referenceName && name.IndexOf('.') != -1) { 
                                // if it's a reference name with a dot, we've actually got a property here... 
                                //
                                int dotIndex = name.IndexOf('.'); 

                                expression = new CodePropertyReferenceExpression(new CodeVariableReferenceExpression(name.Substring(0, dotIndex)), name.Substring(dotIndex + 1));
                            }
                            else { 
                                expression = new CodeVariableReferenceExpression(name);
                            } 
                        } 

                    } 

                    table[value] = expression;
                }
                else { 
                    expression = exp as CodeExpression;
                } 
            } 

            return expression; 
        }

        /// 
        ///  
        ///     Returns the serializer for the given value.  This is cognizant that instance
        ///     attributes may be different from type attributes and will use a custom serializer 
        ///     on the instance if it is present.  If not, it will delegate to the serialization 
        ///     manager.
        ///  
        protected CodeDomSerializer GetSerializer(IDesignerSerializationManager manager, object value) {
            if (value != null) {
                AttributeCollection valueAttributes = TypeDescriptor.GetAttributes(value);
                AttributeCollection typeAttributes = TypeDescriptor.GetAttributes(value.GetType()); 

                if (valueAttributes.Count != typeAttributes.Count) { 
 
                    // Ok, someone has stuffed custom attributes on this instance.  Since
                    // the serialization manager only takes types, we've got to see if 
                    // one of these custom attributes is a designer serializer attribute.

                    string valueSerializerTypeName = null;
 
                    Type desiredSerializerType = typeof(CodeDomSerializer);
 
                    foreach (Attribute a in valueAttributes) { 
                        DesignerSerializerAttribute da = a as DesignerSerializerAttribute;
                        if (da != null) { 
                            Type realSerializerType = manager.GetType(da.SerializerBaseTypeName);
                            if (realSerializerType == desiredSerializerType) {
                                valueSerializerTypeName = da.SerializerTypeName;
                                break; 
                            }
                        } 
                    } 

                    // If we got a value serializer, we've got to do the same thing 
                    // here for the type serializer.  We only care if the two
                    // are different

                    if (valueSerializerTypeName != null) { 
                        foreach (Attribute a in typeAttributes) {
                            DesignerSerializerAttribute da = a as DesignerSerializerAttribute; 
                            if (da != null) { 
                                Type realSerializerType = manager.GetType(da.SerializerBaseTypeName);
                                if (realSerializerType == desiredSerializerType) { 

                                    // Ok, we found a serializer. If it matches the
                                    // one we found for the value, then we can still
                                    // use the default implementation. 
                                    if (valueSerializerTypeName.Equals(da.SerializerTypeName)) {
                                        valueSerializerTypeName = null; 
                                    } 
                                    break;
                                } 
                            }
                        }
                    }
 
                    // Finally, if we got a value serializer, we need to create it and use it.
                    if (valueSerializerTypeName != null) { 
                        Type serializerType = manager.GetType(valueSerializerTypeName); 
                        if (serializerType != null && desiredSerializerType.IsAssignableFrom(serializerType)) {
                            return (CodeDomSerializer)Activator.CreateInstance(serializerType); 
                        }
                    }
                }
            } 

            // for serializing null, we pass null to the serialization manager 
            // otherwise, external IDesignerSerializationProviders wouldn't be given a chance to 
            // serialize null their own special way.
 
            Type t = null;

            if (value != null) {
                t = value.GetType(); 
            }
 
            return (CodeDomSerializer)manager.GetSerializer(t, typeof(CodeDomSerializer)); 
        }
 
        /// 
        /// 
        ///     Returns the serializer for the given value.  This is cognizant that instance
        ///     attributes may be different from type attributes and will use a custom serializer 
        ///     on the instance if it is present.  If not, it will delegate to the serialization
        ///     manager. 
        ///  
        protected CodeDomSerializer GetSerializer(IDesignerSerializationManager manager, Type valueType) {
            return manager.GetSerializer(valueType, typeof(CodeDomSerializer)) as CodeDomSerializer; 
        }

        [SuppressMessage("Microsoft.Performance", "CA1801:AvoidUnusedParameters")]
        protected bool IsSerialized(IDesignerSerializationManager manager, object value) { 
            return IsSerialized(manager, value, false);
        } 
 
        /// 
        ///  
        ///     This method returns true if the given value has been serialized before.  For an object to
        ///     be considered serialized either it or another serializer must have called SetExpression, creating
        ///     a relationship between that object and a referring expression.
        ///  
 	[SuppressMessage("Microsoft.Performance", "CA1801:AvoidUnusedParameters")]
        protected bool IsSerialized(IDesignerSerializationManager manager, object value, bool honorPreset) { 
 
            bool hasExpression = false;
 
            if (manager == null) {
                throw new ArgumentNullException("manager");
            }
 
            if (value == null) {
                throw new ArgumentNullException("value"); 
            } 

            // Is the expression part of a prior SetExpression call? 
            ExpressionTable table = manager.Context[typeof(ExpressionTable)] as ExpressionTable;

            if (table != null && table.GetExpression(value) != null && (!honorPreset || !table.ContainsPresetExpression(value))) {
                hasExpression = true; 
            }
 
            Trace("IsSerialized called for object {0} : {1}", value, hasExpression); 
            return hasExpression;
        } 

        /// 
        /// 
        ///    This method can be used to serialize an expression that represents the creation of the given object. 
        ///    It is aware of instance descriptors and will return true for isComplete if the entire configuration for the
        ///    instance could be achieved. 
        ///  
        protected CodeExpression SerializeCreationExpression(IDesignerSerializationManager manager, object value, out bool isComplete) {
 
            isComplete = false;
            if (manager == null) {
                throw new ArgumentNullException("manager");
            } 

            if (value == null) { 
                throw new ArgumentNullException("value"); 
            }
 
            TypeConverter converter = TypeDescriptor.GetConverter(value);

            // See if there is an ExpressionContext with a preset value we're interested in.  If so,
            // that will dictate our creation expression. 
            ExpressionContext cxt = manager.Context[typeof(ExpressionContext)] as ExpressionContext;
            if (cxt != null && object.ReferenceEquals(cxt.PresetValue, value)) { 
                CodeExpression expression = cxt.Expression; 

                //Okay, we found a preset creation expression. We just need to find if it isComplete. 
                if (converter.CanConvertTo(typeof(InstanceDescriptor))) {
                    InstanceDescriptor descriptor = converter.ConvertTo(value, typeof(InstanceDescriptor)) as InstanceDescriptor;

                    if (descriptor != null && descriptor.MemberInfo != null) { 
                        isComplete = descriptor.IsComplete;
                    } 
                } 

                return expression; 
            }

            // See if there is an instance descriptor for this type.
            if (converter.CanConvertTo(typeof(InstanceDescriptor))) { 
                InstanceDescriptor descriptor = converter.ConvertTo(value, typeof(InstanceDescriptor)) as InstanceDescriptor;
 
                if (descriptor != null && descriptor.MemberInfo != null) { 
                    isComplete = descriptor.IsComplete;
                    return SerializeInstanceDescriptor(manager, value, descriptor); 
                }
            }

            // see if this thing is serialiable 
            if (TypeDescriptor.GetReflectionType(value).IsSerializable && !(value is IComponent && ((IComponent)value).Site != null)) {
                CodeExpression expression = SerializeToResourceExpression(manager, value); 
                TraceIf(expression != null, "Serialized value as a resource."); 
                if (expression != null) {
                    isComplete = true; 
                    return expression;
                }
            }
 
            // No instance descriptor.  See if we can get to a public constructor that takes no arguments
            Type type = TypeDescriptor.GetReflectionType(value); 
            ConstructorInfo ctor = type.GetConstructor(new Type[0]); 

            if (ctor != null) { 
                isComplete = false;
                return new CodeObjectCreateExpression(TypeDescriptor.GetClassName(value), new CodeExpression[0]);
            }
 
            // Nothing worked.
            return null; 
        } 

        ///  
        /// 
        ///    This method returns a unique name for the given object.  It first calls GetName from the serialization
        ///    manager, and if this does not return a name if fabricates a name for the object.  To fabricate a name
        ///    it uses the INameCreationService to create valid names.  If the service is not available instead the 
        ///    method will fabricate a name based on the short type name combined with an index number to make
        ///    it unique. The resulting name is associated with the serialization manager by calling SetName before 
        ///    the new name is returned. 
        /// 
        protected string GetUniqueName(IDesignerSerializationManager manager, object value) { 
            if (manager == null) {
                throw new ArgumentNullException("manager");
            }
 
            if (value == null) {
                throw new ArgumentNullException("value"); 
            } 

            string name = manager.GetName(value); 

            if (name == null) {
                string baseName;
                Type targetType = TypeDescriptor.GetReflectionType(value); 

                INameCreationService ns = manager.GetService(typeof(INameCreationService)) as INameCreationService; 
 
                TraceWarningIf(ns == null, "Need to generate a unique name but we have no name creation service.");
                if (ns != null) { 
                    baseName = ns.CreateName(null, targetType);
                }
                else {
                    baseName = targetType.Name.ToLower(CultureInfo.InvariantCulture); 
                }
 
                int suffixIndex = 1; 
                ComponentCache cache = manager.Context[typeof(ComponentCache)] as ComponentCache;
 
                // Declare this name to the serializer.  If there is already a name defined,
                // keep trying.
                //
                while (true) { 
                    name = string.Format(CultureInfo.CurrentCulture, "{0}{1}", baseName, suffixIndex);
                    if (manager.GetInstance(name) == null && (cache == null || !cache.ContainsLocalName(name))) { 
                        manager.SetName(value, name); 
                        ComponentCache.Entry entry = manager.Context[typeof(ComponentCache.Entry)] as ComponentCache.Entry;
                        if (entry != null) { 
                            entry.AddLocalName(name);
                        }
                        break;
                    } 

                    suffixIndex++; 
                } 
            }
 
            return name;
        }

        ///  
        /// 
        ///     This serializes a single event for the given object. 
        ///  
        protected void SerializeEvent(IDesignerSerializationManager manager, CodeStatementCollection statements, object value, EventDescriptor descriptor) {
 
            if (manager == null) throw new ArgumentNullException("manager");
            if (statements == null) throw new ArgumentNullException("statements");
            if (value == null) throw new ArgumentNullException("value");
            if (descriptor == null) throw new ArgumentNullException("descriptor"); 

            using (TraceScope("CodeDomSerializerBase::SerializeEvent")) { 
                Trace("Name: {0}", descriptor.Name); 
                // Now look for a MemberCodeDomSerializer for the property.  If we can't find one, then we can't serialize
                // the property 
                manager.Context.Push(statements);
                manager.Context.Push(descriptor);
                try {
                    MemberCodeDomSerializer memberSerializer = (MemberCodeDomSerializer)manager.GetSerializer(descriptor.GetType(), typeof(MemberCodeDomSerializer)); 

                    TraceErrorIf(memberSerializer == null, "Event {0} cannot be serialized because it has no serializer.", descriptor.Name); 
                    if (memberSerializer != null && memberSerializer.ShouldSerialize(manager, value, descriptor)) { 
                        memberSerializer.Serialize(manager, value, descriptor, statements);
                    } 
                }
                finally {
                    Debug.Assert(manager.Context.Current == descriptor, "Context stack corrupted.");
                    manager.Context.Pop(); 
                    manager.Context.Pop();
                } 
            } 
        }
 
        /// 
        /// 
        ///     This serializes all events for the given object.
        ///  
        protected void SerializeEvents(IDesignerSerializationManager manager, CodeStatementCollection statements, object value, params Attribute[] filter) {
 
            Trace("CodeDomSerializerBase::SerializeEvents"); 

            // Now walk the events. 
            //
            EventDescriptorCollection events = TypeDescriptor.GetEvents(value, filter).Sort();
            foreach (EventDescriptor evt in events) {
                SerializeEvent(manager, statements, value, evt); 
            }
        } 
 
        /// 
        ///  
        ///     Serializes the given instance descriptor into a code model expression.
        /// 
        private CodeExpression SerializeInstanceDescriptor(IDesignerSerializationManager manager, object value, InstanceDescriptor descriptor) {
            CodeExpression expression = null; 

            using (TraceScope("CodeDomSerializerBase::SerializeInstanceDescriptor")) { 
                Trace("Member : {0}, args : {1}", descriptor.MemberInfo.Name, descriptor.Arguments.Count); 

                // Serialize all of the arguments. 
                //
                CodeExpression[] arguments = new CodeExpression[descriptor.Arguments.Count];
                object[] argumentValues = new object[arguments.Length];
                ParameterInfo[] parameters = null; 

                if (arguments.Length > 0) { 
                    descriptor.Arguments.CopyTo(argumentValues, 0); 
                    MethodBase mi = descriptor.MemberInfo as MethodBase;
                    if (mi != null) { 
                        parameters = mi.GetParameters();
                    }
                }
 
                bool paramsOk = true;
 
                for (int i = 0; i < arguments.Length; i++) { 
                    Debug.Assert(argumentValues != null && parameters != null, "These should have been allocated when the argument array was created.");
                    object arg = argumentValues[i]; 
                    CodeExpression exp = null;
                    ExpressionContext newCxt = null;
                    ExpressionContext cxt = manager.Context[typeof(ExpressionContext)] as ExpressionContext;
 
                    // If there is an ExpressionContext on the stack, we need to fix up its type to be
                    // the parameter type, so the argument objects get serialized correctly. 
                    if (cxt != null) { 
                        newCxt = new ExpressionContext(cxt.Expression, parameters[i].ParameterType, cxt.Owner);
                        manager.Context.Push(newCxt); 
                    }

                    try {
                        exp = SerializeToExpression(manager, arg); 
                    }
                    finally { 
                        if (newCxt != null) { 
                            Debug.Assert(manager.Context.Current == newCxt, "Context stack corrupted.");
                            manager.Context.Pop(); 
                        }
                    }

                    if (exp != null) { 
                        // Assign over.  See if we need a cast first.
                        if (arg != null && !parameters[i].ParameterType.IsAssignableFrom(arg.GetType())) { 
                            exp = new CodeCastExpression(parameters[i].ParameterType, exp); 
                        }
                        arguments[i] = exp; 
                    }
                    else {
                        TraceWarning("Parameter {0} in instance descriptor call {1} could not be serialized.", i, descriptor.GetType().Name);
                        paramsOk = false; 
                        break;
                    } 
                } 

                if (paramsOk) { 
                    Type expressionType = descriptor.MemberInfo.DeclaringType;
                    CodeTypeReference typeRef = new CodeTypeReference(expressionType);

                    if (descriptor.MemberInfo is ConstructorInfo) { 
                        expression = new CodeObjectCreateExpression(typeRef, arguments);
                    } 
                    else if (descriptor.MemberInfo is MethodInfo) { 
                        CodeTypeReferenceExpression typeRefExp = new CodeTypeReferenceExpression(typeRef);
                        CodeMethodReferenceExpression methodRef = new CodeMethodReferenceExpression(typeRefExp, descriptor.MemberInfo.Name); 

                        expression = new CodeMethodInvokeExpression(methodRef, arguments);
                        expressionType = ((MethodInfo)descriptor.MemberInfo).ReturnType;
                    } 
                    else if (descriptor.MemberInfo is PropertyInfo) {
                        CodeTypeReferenceExpression typeRefExp = new CodeTypeReferenceExpression(typeRef); 
                        CodePropertyReferenceExpression propertyRef = new CodePropertyReferenceExpression(typeRefExp, descriptor.MemberInfo.Name); 

                        Debug.Assert(arguments.Length == 0, "Property serialization does not support arguments"); 
                        expression = propertyRef;
                        expressionType = ((PropertyInfo)descriptor.MemberInfo).PropertyType;
                    }
                    else if (descriptor.MemberInfo is FieldInfo) { 
                        Debug.Assert(arguments.Length == 0, "Field serialization does not support arguments");
 
                        CodeTypeReferenceExpression typeRefExp = new CodeTypeReferenceExpression(typeRef); 

                        expression = new CodeFieldReferenceExpression(typeRefExp, descriptor.MemberInfo.Name); 
                        expressionType = ((FieldInfo)descriptor.MemberInfo).FieldType;
                    }
                    else {
                        Debug.Fail("Unrecognized reflection type in instance descriptor: " + descriptor.MemberInfo.GetType().Name); 
                    }
 
                    // Finally, check to see if our value is assignable from the expression type.  If not, 
                    // then supply a cast.  The value may be an internal or protected type; if it is,
                    // then walk up its hierarchy until we find one that is public. 
                    //
                    Type targetType = value.GetType();

                    while (!targetType.IsPublic) { 
                        targetType = targetType.BaseType;
                    } 
 
                    if (!targetType.IsAssignableFrom(expressionType)) {
                        Trace("Supplying cast from {0} to {1}.", expressionType.Name, targetType.Name); 
                        expression = new CodeCastExpression(targetType, expression);
                    }
                }
            } 

            return expression; 
        } 

        ///  
        /// 
        ///     This serializes all properties for the given object, using the provided filter.
        /// 
        protected void SerializeProperties(IDesignerSerializationManager manager, CodeStatementCollection statements, object value, Attribute[] filter) { 
            using (TraceScope("CodeDomSerializerBase::SerializeProperties")) {
                // Now walk the properties. 
                // 
                PropertyDescriptorCollection properties = GetFilteredProperties(manager, value, filter).Sort();
                InheritanceAttribute inheritance = (InheritanceAttribute)TypeDescriptor.GetAttributes(value)[typeof(InheritanceAttribute)]; 

                if (inheritance == null) {
                    inheritance = InheritanceAttribute.NotInherited;
                } 

                manager.Context.Push(inheritance); 
                try { 
                    foreach (PropertyDescriptor property in properties) {
                        if (!property.Attributes.Contains(DesignerSerializationVisibilityAttribute.Hidden)) { 
                            SerializeProperty(manager, statements, value, property);
                        }
                    }
                } 
                finally {
                    Debug.Assert(manager.Context.Current == inheritance, "Sombody messed up our context stack."); 
                    manager.Context.Pop(); 
                }
            } 
        }

        /// 
        ///  
        ///     This method will inspect all of the properties on the given object fitting the filter, and check for that
        ///     property in a resource blob.  This is useful for deserializing properties that cannot be represented 
        ///     in code, such as design-time properties. 
        /// 
        protected void SerializePropertiesToResources(IDesignerSerializationManager manager, CodeStatementCollection statements, object value, Attribute[] filter) { 
            using (TraceScope("ComponentCodeDomSerializerBase::SerializePropertiesToResources")) {
                PropertyDescriptorCollection props = TypeDescriptor.GetProperties(value, filter);

                manager.Context.Push(statements); 

                try { 
                    CodeExpression target = SerializeToExpression(manager, value); 

                    if (target != null) { 

                        CodePropertyReferenceExpression propertyRef = new CodePropertyReferenceExpression(target, string.Empty);

                        foreach (PropertyDescriptor property in props) { 
                            TraceWarningIf(property.Attributes.Contains(DesignerSerializationVisibilityAttribute.Content), "PersistContents property " + property.Name + " cannot be serialized to resources.");
 
                            ExpressionContext tree = new ExpressionContext(propertyRef, property.PropertyType, value); 

                            manager.Context.Push(tree); 
                            try {
                                if (property.Attributes.Contains(DesignerSerializationVisibilityAttribute.Visible)) {
                                    propertyRef.PropertyName = property.Name;
                                    Trace("Property : {0}", property.Name); 

                                    string name; 
 
                                    if (target is CodeThisReferenceExpression) {
                                        name = "$this"; 
                                    }
                                    else {
                                        name = manager.GetName(value);
                                    } 

                                    name = string.Format(CultureInfo.CurrentCulture, "{0}.{1}", name, property.Name); 
                                    ResourceCodeDomSerializer.Default.SerializeMetadata(manager, name, property.GetValue(value), property.ShouldSerializeValue(value)); 
                                }
                            } 
                            finally {
                                Debug.Assert(manager.Context.Current == tree, "Context stack corrupted.");
                                manager.Context.Pop();
                            } 
                        }
                    } 
                } 
                finally {
                    Debug.Assert(manager.Context.Current == statements, "Context stack corrupted."); 
                    manager.Context.Pop();
                }
            }
        } 

        ///  
        ///  
        ///     This serializes the given proeprty for the given object.
        ///  
        protected void SerializeProperty(IDesignerSerializationManager manager, CodeStatementCollection statements, object value, PropertyDescriptor propertyToSerialize) {
            if (manager == null) throw new ArgumentNullException("manager");

            if (value == null) throw new ArgumentNullException("value"); 

            if (propertyToSerialize == null) throw new ArgumentNullException("propertyToSerialize"); 
 
            if (statements == null) throw new ArgumentNullException("statements");
 
            Trace("CodeDomSerializerBase::SerializeProperty {0}", propertyToSerialize.Name);

            // Now look for a MemberCodeDomSerializer for the property.  If we can't find one, then we can't serialize
            // the property 
            manager.Context.Push(statements);
            manager.Context.Push(propertyToSerialize); 
            try { 
                MemberCodeDomSerializer memberSerializer = (MemberCodeDomSerializer)manager.GetSerializer(propertyToSerialize.GetType(), typeof(MemberCodeDomSerializer));
 
                TraceErrorIf(memberSerializer == null, "Property {0} cannot be serialized because it has no serializer.", propertyToSerialize.Name);
                if (memberSerializer != null && memberSerializer.ShouldSerialize(manager, value, propertyToSerialize)) {
                    memberSerializer.Serialize(manager, value, propertyToSerialize, statements);
                } 
            }
            finally { 
                Debug.Assert(manager.Context.Current == propertyToSerialize, "Context stack corrupted."); 
                manager.Context.Pop();
                manager.Context.Pop(); 
            }
        }

        ///  
        /// 
        ///     Writes the given resource value under the given name.  The resource is written to the 
        ///     current CultureInfo the user is using to design with. 
        /// 
        protected void SerializeResource(IDesignerSerializationManager manager, string resourceName, object value) { 
            ResourceCodeDomSerializer.Default.WriteResource(manager, resourceName, value);
        }

        ///  
        /// 
        ///     Writes the given resource value under the given name.  The resource is written to the 
        ///     invariant culture. 
        /// 
        protected void SerializeResourceInvariant(IDesignerSerializationManager manager, string resourceName, object value) { 
            ResourceCodeDomSerializer.Default.WriteResourceInvariant(manager, resourceName, value);
        }

        ///  
        /// 
        ///    This is a helper method that serializes a value to an expression.  It will return a CodeExpression if the 
        ///    value can be serialized, or null if it can't.  SerializeToExpression uses the following rules for serializing types: 
        ///    1.   It first calls GetExpression to see if an expression has already been created for the object.  If so, it
        ///        returns the existing expression. 
        ///    2.   It then locates the object's serializer, and asks it to serialize.
        ///    3.   If the return value of the object's serializer is a CodeExpression, the expression is returned.
        ///    4.   It finally makes one last call to GetExpression to see if the serializer added an expression.
        ///    5.   Finally, it returns null. 
        ///
        ///    If no expression could be created and no suitable serializer could be found, an error will be 
        ///    reported through the serialization manager.  No error will be reported if a serializer was found 
        ///    but it failed to produce an expression.  It is assumed that the serializer either already reported
        ///    the error, or does not wish to serialize the object. 
        /// 
        protected CodeExpression SerializeToExpression(IDesignerSerializationManager manager, object value) {
            CodeExpression expression = null;
 
            using (TraceScope("SerializeToExpression")) {
                // We do several things here: 
                // 
                // First, we check to see if there is already an expression for this object by calling
                // IsSerialized / GetExpression. 
                //
                // Failing that we check GetLegacyExpression to see if we are working with an old serializer.
                //
                // Failing that, we invoke the object's serializer.  If that serializer returned a CodeExpression, 
                // we will use it.
                // 
                // If the serializer did not return a code expression, we call GetExpression one last time to 
                // see if the serializer added an expression.  If it did, we use it. Otherwise we return
                // null. 
                //
                // If the serializer was invoked and it created one or more statements those statements will
                // be added to a statement collection.  Additionally, if there is a statement context that contains
                // a statement table for this object we will push that statement table onto the context stack in 
                // case someone else needs statements.
                if (value != null) { 
                    if (IsSerialized(manager, value)) { 
                        expression = GetExpression(manager, value);
                        TraceIf(expression != null, "Existing expression found : {0}", expression); 
                    }
                    else {
                        expression = GetLegacyExpression(manager, value);
                        if (expression != null) { 
                            TraceWarning("Using legacy expression guard to prevent recursion.  Serializer for {0} should be rewritten to handle GetExpression / SetExpression.", value);
                            SetExpression(manager, value, expression); 
                        } 
                    }
                } 

                if (expression == null) {
                    CodeDomSerializer serializer = GetSerializer(manager, value);
 
                    if (serializer != null) {
                        Trace("Invoking serializer {0}", serializer.GetType().Name); 
 
                        CodeStatementCollection saveStatements = null;
 
                        if (value != null) {

                            // The Whidbey model for serializing a complex object is to call
                            // SetExpression with the object's reference expression and then 
                            // call on the various Serialize Property / Event methods.  This is
                            // incompatible with legacy code, and if not handled legacy code may 
                            // serialize incorrectly or even stack fault.  To handle this, we keep 
                            // a private "Legacy Expression Table".  This is a table that we fill in
                            // here.  We don't fill in the actual legacy expression here.  Rather, 
                            // we fill it with a marker value and obtain the legacy expression
                            // above in GetLegacyExpression.  If we hit this case, we then save
                            // the expression in GetExpression so that future calls to IsSerialized
                            // will succeed. 

                            SetLegacyExpression(manager, value); 
 
                            StatementContext statementCxt = manager.Context[typeof(StatementContext)] as StatementContext;
 
                            if (statementCxt != null) {
                                saveStatements = statementCxt.StatementCollection[value];
                            }
 
                            if (saveStatements != null) {
                                manager.Context.Push(saveStatements); 
                            } 
                        }
 
                        object result = null;

                        try {
                            result = serializer.Serialize(manager, value); 
                        }
                        finally { 
                            if (saveStatements != null) { 
                                Debug.Assert(manager.Context.Current == saveStatements, "Context stack corrupted.");
                                manager.Context.Pop(); 
                            }
                        }

                        expression = result as CodeExpression; 
                        if (expression == null && value != null) {
                            expression = GetExpression(manager, value); 
                        } 

                        // If the result is a statement or a group of statements, we need to 
                        // see if there is a code statement collection on the stack we can push the
                        // statements into.
                        CodeStatementCollection statements = result as CodeStatementCollection;
 
                        if (statements == null) {
                            CodeStatement statement = result as CodeStatement; 
 
                            if (statement != null) {
                                statements = new CodeStatementCollection(); 
                                statements.Add(statement);
                            }
                        }
 
                        if (statements != null) {
                            Trace("Serialization produced additional statements"); 
 
                            // See if we have a place for these statements to be stored.  If not, then
                            // check the context. 

                            if (saveStatements == null) {
                                saveStatements = manager.Context[typeof(CodeStatementCollection)] as CodeStatementCollection;
                            } 

                            if (saveStatements != null) { 
                                Trace("Saving in context stack statement collection"); 
                                Debug.Assert(saveStatements != statements, "The serializer returned the same collection that exists on the context stack.");
                                saveStatements.AddRange(statements); 
                            }
                            else {
                                // If we got here we will be losing data because we have no avenue to save these statements.  Inform the user.
                                string valueName = "(null)"; 

                                if (value != null) { 
                                    valueName = manager.GetName(value); 
                                    if (valueName == null) {
                                        valueName = value.GetType().Name; 
                                    }
                                }

                                TraceError("Serialization produced a set of statements but there is no statement collection on the stack to receive them."); 
                                manager.ReportError(SR.GetString(SR.SerializerLostStatements, valueName));
                            } 
                        } 
                    }
                    else { 
                        TraceError("No serializer for data type: {0}", (value == null ? "(null)" : value.GetType().Name));
                        manager.ReportError(SR.GetString(SR.SerializerNoSerializerForComponent, value.GetType().FullName));
                    }
                } 
            }
 
            return expression; 
        }
 
        /// 
        /// 
        ///     Serializes the given object to a resource and returns a code expression that represents the resource.
        ///     This will return null if the value cannot be serialized.  If ensureInvariant is true, this will ensure that 
        ///     new values make their way into the invariant culture.  Normally, this is desirable. Otherwise a resource
        ///     GetValue call could fail if reading from a culture that doesn't have a value.  You should only pass 
        ///     false to ensureInvariant when you intend to read resources differently than directly asking for a value. 
        ///     The default value of insureInvariant is true.
        ///  
        protected CodeExpression SerializeToResourceExpression(IDesignerSerializationManager manager, object value) {
            return SerializeToResourceExpression(manager, value, true);
        }
 
        /// 
        ///  
        ///     Serializes the given object to a resource and returns a code expression that represents the resource. 
        ///     This will return null if the value cannot be serialized.  If ensureInvariant is true, this will ensure that
        ///     new values make their way into the invariant culture.  Normally, this is desirable. Otherwise a resource 
        ///     GetValue call could fail if reading from a culture that doesn't have a value.  You should only pass
        ///     false to ensureInvariant when you intend to read resources differently than directly asking for a value.
        ///     The default value of insureInvariant is true.
        ///  
        protected CodeExpression SerializeToResourceExpression(IDesignerSerializationManager manager, object value, bool ensureInvariant) {
            CodeExpression result = null; 
            if (value == null || value.GetType().IsSerializable) { 
                CodeStatementCollection saveStatements = null;
                if (value != null) { 
                    StatementContext statementCxt = manager.Context[typeof(StatementContext)] as StatementContext;

                    if (statementCxt != null) {
                        saveStatements = statementCxt.StatementCollection[value]; 
                    }
 
                    if (saveStatements != null) { 
                        manager.Context.Push(saveStatements);
                    } 
                }

                try {
                    result = ResourceCodeDomSerializer.Default.Serialize(manager, value, false, ensureInvariant) as CodeExpression; 
                }
                finally { 
                    if (saveStatements != null) { 
                        Debug.Assert(manager.Context.Current == saveStatements, "Context stack corrupted.");
                        manager.Context.Pop(); 
                    }
                }
            }
 
            return result;
        } 
 
        [SuppressMessage("Microsoft.Performance", "CA1801:AvoidUnusedParameters")]
        protected void SetExpression(IDesignerSerializationManager manager, object value, CodeExpression expression) { 
            SetExpression(manager, value, expression, false);
        }

        ///  
        /// 
        ///    This is a helper method that associates a CodeExpression with an object.  Objects that have been associated 
        ///    with expressions in this way are accessible through the GetExpression method.  SetExpression stores its 
        ///    expression table as an appended object on the context stack so it is accessible by any serializer's
        ///    GetExpression method. 
        /// 
	[SuppressMessage("Microsoft.Performance", "CA1801:AvoidUnusedParameters")]
        protected void SetExpression(IDesignerSerializationManager manager, object value, CodeExpression expression, bool isPreset) {
 
            if (manager == null) {
                throw new ArgumentNullException("manager"); 
            } 

            if (value == null) { 
                throw new ArgumentNullException("value");
            }

            if (expression == null) { 
                throw new ArgumentNullException("expression");
            } 
 
            ExpressionTable table = (ExpressionTable)manager.Context[typeof(ExpressionTable)];
            if (table == null) { 
                table = new ExpressionTable();
                manager.Context.Append(table);
            }
 
            Trace("Set expression {0} for object {1}", expression, value);
 
            // in debug builds, save off who performed this set expression.  It's 
            // very valuable to know.
#if DEBUG 


            if (traceSerialization.TraceVerbose) {
                expression.UserData["StackTrace"] = Environment.StackTrace; 
            }
            else { 
                 // Default to off as snapping the stack takes too much time in DEBUG to leave on permanently. 
                 expression.UserData["StackTrace"] =  "To enable - turn on DesignerSerialization TraceSwitch";
            } 

            CodeExpression existingExpression = table.GetExpression(value);
            if (existingExpression != null && !isPreset) {
                Debug.Fail("There shouldn't be an expression already associated with this object : " + manager.GetName(value)); 
                string stack = existingExpression.UserData["StackTrace"] as string;
                if (stack == null) { 
                    stack = "unknown"; 
                }
                TraceWarning("Duplicate expression on context stack for value {0}.  Original expression callstack: {1}", value, stack); 
            }
#endif
            table.SetExpression(value, expression, isPreset);
        } 

        ///  
        ///     This method configures "value" to support a legacy expression, enabling legacy serialization and 
        ///     preventing recursion.
        ///  
        private void SetLegacyExpression(IDesignerSerializationManager manager, object value) {

            if (value is IComponent) {
                LegacyExpressionTable table = (LegacyExpressionTable)manager.Context[typeof(LegacyExpressionTable)]; 
                if (table == null) {
                    table = new LegacyExpressionTable(); 
                    manager.Context.Append(table); 
                }
 
                table[value] = value;
            }
        }
 
        /// 
        ///    Tracing functions for debugging. 
        ///  
        [Conditional("DEBUG")]
        internal static void Trace(string message, params object[] values) { 
            if (traceSerialization.TraceVerbose) {
                int indent = 0;
                int oldIndent = Debug.IndentLevel;
 
                if (traceScope != null) indent = traceScope.Count;
 
                try { 
                    Debug.IndentLevel = indent;
                    Debug.WriteLine(string.Format(CultureInfo.CurrentCulture, message, values)); 
                }
                finally {
                    Debug.IndentLevel = oldIndent;
                } 
            }
        } 
 
        /// 
        ///    Tracing functions for debugging. 
        /// 
        [Conditional("DEBUG")]
        internal static void Trace(CodeTypeDeclaration typeDecl) {
            if (traceSerialization.TraceInfo) { 
                Debug.WriteLine("---------------------------- Generated Code ----------------------------");
                System.IO.StringWriter sw = new System.IO.StringWriter(CultureInfo.InvariantCulture); 
                new Microsoft.CSharp.CSharpCodeProvider().GenerateCodeFromType(typeDecl, sw, new CodeGeneratorOptions()); 
                Debug.WriteLine(sw.ToString());
            } 
        }

        /// 
        ///    Tracing functions for debugging. 
        /// 
        [Conditional("DEBUG")] 
        internal static void TraceError(string message, params object[] values) { 
            if (traceSerialization.TraceError) {
                string scope = string.Empty; 

                if (traceScope != null) {
                    foreach (string scopeName in traceScope) {
                        if (scope.Length > 0) { 
                            scope = "/" + scope;
                        } 
 
                        scope = scopeName + scope;
                    } 
                }

                Debug.WriteLine("***************************************************");
                Debug.WriteLine(string.Format(CultureInfo.CurrentCulture, "*** ERROR :{0}", string.Format(CultureInfo.CurrentCulture, message, values))); 
                Debug.WriteLine(string.Format(CultureInfo.CurrentCulture, "*** SCOPE :{0}", scope));
                Debug.WriteLine("***************************************************"); 
            } 
        }
 
        /// 
        ///    Tracing functions for debugging.
        /// 
        [Conditional("DEBUG")] 
        internal static void TraceErrorIf(bool condition, string message, params object[] values) {
            if (condition) TraceError(message, values); 
        } 

        ///  
        ///    Tracing functions for debugging.
        /// 
        [Conditional("DEBUG")]
        internal static void TraceIf(bool condition, string message, params object[] values) { 
            if (condition) Trace(message, values);
        } 
 
        /// 
        ///    Tracing functions for debugging. 
        /// 
        internal static IDisposable TraceScope(string name) {

#if DEBUG 
            if (traceScope == null) {
                traceScope = new Stack(); 
            } 

            Trace(name); 
            traceScope.Push(name);
#endif
            return new TracingScope();
        } 

        ///  
        ///    Tracing functions for debugging. 
        /// 
        [Conditional("DEBUG")] 
        internal static void TraceWarning(string message, params object[] values) {
            if (traceSerialization.TraceWarning) {
                string scope = string.Empty;
 
                if (traceScope != null) {
                    foreach (string scopeName in traceScope) { 
                        if (scope.Length > 0) { 
                            scope = "/" + scope;
                        } 

                        scope = scopeName + scope;
                    }
                } 

                Debug.WriteLine("***************************************************"); 
                Debug.WriteLine(string.Format(CultureInfo.CurrentCulture, "*** WARNING :{0}", string.Format(CultureInfo.CurrentCulture, message, values))); 
                Debug.WriteLine(string.Format(CultureInfo.CurrentCulture, "*** SCOPE :{0}", scope));
                Debug.WriteLine("***************************************************"); 
            }
        }

        ///  
        ///    Tracing functions for debugging.
        ///  
        [Conditional("DEBUG")] 
        internal static void TraceWarningIf(bool condition, string message, params object[] values) {
            if (condition) TraceWarning(message, values); 
        }

        private class LegacyExpressionTable : Hashtable {
        } 

        private struct TracingScope : IDisposable { 
            public void Dispose() { 
                if (traceScope != null) traceScope.Pop();
            } 
        }

        /// 
        ///     Utility method that adds the given statement to our _statementTable dictionary under the 
        ///     given name.
        ///  
        private static void AddStatement(IDictionary table, string name, CodeStatement statement) { 

            OrderedCodeStatementCollection statements; 

            if (table.Contains(name)) {
                statements = (OrderedCodeStatementCollection)table[name];
            } 
            else {
                // push in an order key so we know what position this item was in the list of declarations. 
                // this allows us to preserve ZOrder. 
                //
                statements = new OrderedCodeStatementCollection(); 
                statements.Order = table.Count;
                statements.Name = name;
                table[name] = statements;
            } 

            statements.Add(statement); 
        } 

        internal static Type GetType(ITypeResolutionService trs, string name, Dictionary names) { 
            Type type = null;

            if (names != null && names.ContainsKey(name)) {
                string typeName = names[name]; 
                if (trs != null && !string.IsNullOrEmpty(typeName)) {
                    type = trs.GetType(typeName, false); 
                } 
            }
            return type; 
        }

        internal static void FillStatementTable(IDesignerSerializationManager manager, IDictionary table, CodeStatementCollection statements) {
            FillStatementTable(manager, table, null, statements, null); 
        }
 
        ///  
        ///     For those statements who
        ///     have a LHS that points to a name in our nametable, we add the statement to a Statement 
        ///     Collection within the table dictionary.  This allows us to very quickly
        ///     put to gether what statements are associated with what names.
        ///     The return value of this method is a list of statements that have no
        ///     LHS.  The CodeDomComponentSerializationService needs this to 
        ///     ensure it deserializes all the required statements
        ///  
        internal static void FillStatementTable(IDesignerSerializationManager manager, IDictionary table, Dictionary names, CodeStatementCollection statements, string className) { 
            using (TraceScope("CodeDomSerializerBase::FillStatementTable")) {
 
                // Statements we look for.
                CodeAssignStatement assign;
                CodeAttachEventStatement attachEvent;
                CodeRemoveEventStatement removeEvent; 
                CodeExpressionStatement expressionStmt = null;
                CodeVariableDeclarationStatement variableDecl; 
 

                ITypeResolutionService trs = manager.GetService(typeof(ITypeResolutionService)) as ITypeResolutionService; 

                // Look in the method body to try to find statements with a LHS that
                // points to a name in our nametable.
                foreach (CodeStatement statement in statements) { 
                    CodeExpression expression = null;
 
                    if ((assign = statement as CodeAssignStatement) != null) { 
                        Trace("Processing CodeAssignStatement");
                        expression = assign.Left; 
                    }
                    else if ((attachEvent = statement as CodeAttachEventStatement) != null) {
                        Trace("Processing CodeAttachEventStatement");
                        expression = attachEvent.Event; 
                    }
                    else if ((removeEvent = statement as CodeRemoveEventStatement) != null) { 
                        Trace("Processing CodeRemoveEventStatement"); 
                        expression = removeEvent.Event;
                    } 
                    else if ((expressionStmt = statement as CodeExpressionStatement) != null) {
                        Trace("Processing CodeExpressionStatement");
                        expression = expressionStmt.Expression;
                    } 
                    else if ((variableDecl = statement as CodeVariableDeclarationStatement) != null) {
                        Trace("Processing CodeVariableDeclarationStatement"); 
 
                        AddStatement(table, variableDecl.Name, variableDecl);
 
                        if (names != null && variableDecl.Type != null && !string.IsNullOrEmpty(variableDecl.Type.BaseType)) {
                            names[variableDecl.Name] = GetTypeNameFromCodeTypeReference(manager, variableDecl.Type);
                        }
 
                        expression = null;
                    } 
 
                    // Expressions we look for.
                    CodeCastExpression castEx; 
                    CodeDelegateCreateExpression delegateCreateEx;
                    CodeDelegateInvokeExpression delegateInvokeEx;
                    CodeDirectionExpression directionEx;
                    CodeEventReferenceExpression eventReferenceEx; 
                    CodeMethodInvokeExpression methodInvokeEx;
                    CodeMethodReferenceExpression methodReferenceEx; 
                    CodeArrayIndexerExpression arrayIndexerEx; 
                    CodeFieldReferenceExpression fieldReferenceEx;
                    CodePropertyReferenceExpression propertyReferenceEx; 
                    CodeVariableReferenceExpression variableReferenceEx;

                    if (expression != null) {
                        // Simplify the expression as much as we can, looking for our target 
                        // object in the process.  If we find an expression that refers to our target
                        // object, we're done and can move on to the next statement. 
                        while (true) { 
                            if ((castEx = expression as CodeCastExpression) != null) {
                                Trace("Simplifying CodeCastExpression"); 
                                expression = castEx.Expression;
                            }
                            else if ((delegateCreateEx = expression as CodeDelegateCreateExpression) != null) {
                                Trace("Simplifying CodeDelegateCreateExpression"); 
                                expression = delegateCreateEx.TargetObject;
                            } 
                            else if ((delegateInvokeEx = expression as CodeDelegateInvokeExpression) != null) { 
                                Trace("Simplifying CodeDelegateInvokeExpression");
                                expression = delegateInvokeEx.TargetObject; 
                            }
                            else if ((directionEx = expression as CodeDirectionExpression) != null) {
                                Trace("Simplifying CodeDirectionExpression");
                                expression = directionEx.Expression; 
                            }
                            else if ((eventReferenceEx = expression as CodeEventReferenceExpression) != null) { 
                                Trace("Simplifying CodeEventReferenceExpression"); 
                                expression = eventReferenceEx.TargetObject;
                            } 
                            else if ((methodInvokeEx = expression as CodeMethodInvokeExpression) != null) {
                                Trace("Simplifying CodeMethodInvokeExpression");
                                expression = methodInvokeEx.Method;
                            } 
                            else if ((methodReferenceEx = expression as CodeMethodReferenceExpression) != null) {
                                Trace("Simplifying CodeMethodReferenceExpression"); 
                                expression = methodReferenceEx.TargetObject; 
                            }
                            else if ((arrayIndexerEx = expression as CodeArrayIndexerExpression) != null) { 
                                Trace("Simplifying CodeArrayIndexerExpression");
                                expression = arrayIndexerEx.TargetObject;
                            }
                            else if ((fieldReferenceEx = expression as CodeFieldReferenceExpression) != null) { 
                                // For fields we need to check to see if the field name is equal to the target object.
                                // If it is, then we have the expression we want.  We can add the statement here 
                                // and then break out of our loop. 
                                //
                                // Note:  We cannot validate that this is a name in our nametable.  The nametable 
                                // only contains names we have discovered through code parsing and will not include
                                // data from any inherited objects.  We accept the field now, and then fail later
                                // if we try to resolve it to an object and we can't find it.
                                // 
                                bool addedStatement = false;
 
                                if (fieldReferenceEx.TargetObject is CodeThisReferenceExpression) { 

                                    Type type = GetType(trs, fieldReferenceEx.FieldName, names); 
                                    if (type != null) {
                                        CodeDomSerializer serializer = manager.GetSerializer(type, typeof(CodeDomSerializer)) as CodeDomSerializer;
                                        if (serializer != null) {
                                            string componentName = serializer.GetTargetComponentName(statement, expression, type); 
                                            if (!string.IsNullOrEmpty(componentName)) {
                                                AddStatement(table, componentName, statement); 
                                                addedStatement = true; 
                                            }
                                        } 
                                    }
                                    if (!addedStatement) {
                                        // we still want to do this in case of the "Note" above.
                                        AddStatement(table, fieldReferenceEx.FieldName, statement); 
                                    }
                                    break; 
                                } 
                                else {
                                    Trace("Simplifying CodeFieldReferenceExpression"); 
                                    expression = fieldReferenceEx.TargetObject;
                                }
                            }
                            else if ((propertyReferenceEx = expression as CodePropertyReferenceExpression) != null) { 
                                // For properties we need to check to see if the property name is equal to the target object.
                                // If it is, then we have the expression we want.  We can add the statement here 
                                // and then break out of our loop. 
                                //
                                if (propertyReferenceEx.TargetObject is CodeThisReferenceExpression && (names == null || names.ContainsKey(propertyReferenceEx.PropertyName))) { 
                                    AddStatement(table, propertyReferenceEx.PropertyName, statement);
                                    break;
                                }
                                else { 
                                    Trace("Simplifying CodePropertyReferenceExpression");
                                    expression = propertyReferenceEx.TargetObject; 
                                } 
                            }
                            else if ((variableReferenceEx = expression as CodeVariableReferenceExpression) != null) { 
                                // For variables we need to check to see if the variable name is equal to the target object.
                                // If it is, then we have the expression we want.  We can add the statement here
                                // and then break out of our loop.
                                // 
                                bool statementAdded = false;
                                if (names != null) { 
 
                                    Type type = GetType(trs, variableReferenceEx.VariableName, names);
                                    if (type != null) { 
                                        CodeDomSerializer serializer = manager.GetSerializer(type, typeof(CodeDomSerializer)) as CodeDomSerializer;

                                        if (serializer != null) {
                                            string componentName = serializer.GetTargetComponentName(statement, expression, type); 
                                            if (!string.IsNullOrEmpty(componentName)) {
                                                AddStatement(table, componentName, statement); 
                                                statementAdded = true; 
                                            }
                                        } 
                                    }
                                }
                                else {
                                    AddStatement(table, variableReferenceEx.VariableName, statement); 
                                    statementAdded = true;
                                } 
                                if (!statementAdded) { 
                                    TraceError("Variable {0} used before it was declared.", variableReferenceEx.VariableName);
                                    manager.ReportError(new CodeDomSerializerException(SR.GetString(SR.SerializerUndeclaredName, variableReferenceEx.VariableName), manager)); 
                                }
                                break;
                            }
                            else if (expression is CodeThisReferenceExpression || expression is CodeBaseReferenceExpression) { 
                                // We cannot go any further than "this".  So, we break out
                                // of the loop.  We file this statement under the root object. 
                                // 
                                Debug.Assert(className != null, "FillStatementTable expected a valid className but received null");
                                if (className != null) { 
                                    AddStatement(table, className, statement);
                                }
                                break;
                            } 
                            else {
                                // We cannot simplify this expression any further, so we stop looping. 
                                // 
                                break;
                            } 
                        }
                    }
                }
            } 
        }
 
        internal class OrderedCodeStatementCollection : CodeStatementCollection { 
            public int Order;
            public string Name; 
        }
    }
}
 


// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.


                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK