CodeDomDesignerLoader.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 / Host / Serialization / CodeDomDesignerLoader.cs / 1 / CodeDomDesignerLoader.cs

                            //------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 

namespace System.ComponentModel.Design.Serialization { 
 
    using System;
    using System.CodeDom; 
    using System.CodeDom.Compiler;
    using System.Collections;
    using System.Collections.Generic;
    using System.Collections.Specialized; 
    using System.Design;
    using System.Diagnostics; 
    using System.Globalization; 
    using System.Reflection;
    using System.Text; 
    using System.Windows.Forms;
    using Microsoft.Internal.Performance;

    ///  
    /// 
    ///     DesignerLoader.  This class is responsible for loading a designer document. 
    ///     Where and how this load occurs is a private matter for the designer loader. 
    ///     The designer loader will be handed to an IDesignerHost instance.  This instance,
    ///     when it is ready to load the document, will call BeginLoad, passing an instance 
    ///     of IDesignerLoaderHost.  The designer loader will load up the design surface
    ///     using the host interface, and call EndLoad on the interface when it is done.
    ///     The error collection passed into EndLoad should be empty or null to indicate a
    ///     successful load, or it should contain a collection of exceptions that 
    ///     describe the error.
    /// 
    ///     Once a document is loaded, the designer loader is also responsible for 
    ///     writing any changes made to the document back whatever storage the
    ///     loader used when loading the document. 
    /// 
    [System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.InheritanceDemand, Name = "FullTrust")]
    [System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.LinkDemand, Name = "FullTrust")]
    public abstract class CodeDomDesignerLoader : BasicDesignerLoader, INameCreationService, IDesignerSerializationService { 
        private static TraceSwitch traceCDLoader = new TraceSwitch("CodeDomDesignerLoader", "Trace CodeDomDesignerLoader");
        private static CodeMarkers codemarkers = CodeMarkers.Instance; 
        private static readonly int StateCodeDomDirty = BitVector32.CreateMask();                       // True if the code dom tree is dirty, meaning it must be integrated back with the code file. 
        private static readonly int StateCodeParserChecked = BitVector32.CreateMask(StateCodeDomDirty);      // True if we have searched for a parser.
        private static readonly int StateOwnTypeResolution = BitVector32.CreateMask(StateCodeParserChecked); // True if we have added our own type resolution service 

        // State for the designer loader.
        //
        private BitVector32 _state = new BitVector32(); 
        private IExtenderProvider[] _extenderProviders;
        private IExtenderProviderService _extenderProviderService; 
 
        // State for the code dom parser / generator
        // 
        private ICodeGenerator _codeGenerator;

        // The following fields are setup by EnsureDocument and deleted by ClearDocument.
        // 
        private CodeDomSerializer _rootSerializer;
        private TypeCodeDomSerializer _typeSerializer; 
        private CodeCompileUnit _documentCompileUnit; 
        private CodeNamespace _documentNamespace;
        private CodeTypeDeclaration _documentType; 

        /// 
        /// 
        ///     This abstract property returns the code dom provider that should 
        ///     be used by this designer loader.
        ///  
        protected abstract CodeDomProvider CodeDomProvider { get; } 

        ///  
        /// 
        ///     The TypeResolutionService property returns a type resolution service that the code dom
        ///     serializers will use when resolving types.  The CodeDomDesignerLoader automatically
        ///     adds this type resolver as a service to the service container during Initialize if it 
        ///     is non-null.  While the type resolution service is optional in many scenarios, it is required for
        ///     code interpretation because source code contains type names, but no assembly references. 
        ///  
        protected abstract ITypeResolutionService TypeResolutionService { get; }
 
        /// 
        ///     This is the reverse of EnsureDocument.  It clears the document state which will
        ///     cause us to parse the next time we need to access it.
        ///  
        private void ClearDocument() {
            if (_documentType != null) { 
                LoaderHost.RemoveService(typeof(CodeTypeDeclaration)); 
                _documentType = null;
                _documentNamespace = null; 
                _documentCompileUnit = null;
                _rootSerializer = null;
                _typeSerializer = null;
            } 
        }
 
        ///  
        /// 
        ///     Disposes this designer loader.  The designer host will call 
        ///     this method when the design document itself is being destroyed.
        ///     Once called, the designer loader will never be called again.
        ///     This implementation flushes any changes and removes any
        ///     previously added services. 
        /// 
        public override void Dispose() { 
            IDesignerHost host = GetService(typeof(IDesignerHost)) as IDesignerHost; 
            IComponentChangeService cs = GetService(typeof(IComponentChangeService)) as IComponentChangeService;
 
            if (cs != null) {
                cs.ComponentRemoved -= new ComponentEventHandler(this.OnComponentRemoved);
                cs.ComponentRename -= new ComponentRenameEventHandler(OnComponentRename);
            } 

            if (host != null) { 
                host.RemoveService(typeof(INameCreationService)); 
                host.RemoveService(typeof(IDesignerSerializationService));
                host.RemoveService(typeof(ComponentSerializationService)); 

                if (_state[StateOwnTypeResolution]) {
                    host.RemoveService(typeof(ITypeResolutionService));
                    _state[StateOwnTypeResolution] = false; 
                }
            } 
 
            if (_extenderProviderService != null) {
                foreach (IExtenderProvider p in _extenderProviders) { 
                    _extenderProviderService.RemoveExtenderProvider(p);
                }
            }
 
            base.Dispose();
        } 
 
        /// 
        ///     Internal debug method to dump a code dom tree to text. 
        /// 
#if DEBUG
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2102:CatchNonClsCompliantExceptionsInGeneralHandlers")]
        internal static void DumpTypeDeclaration(CodeTypeDeclaration typeDecl) { 
            if (typeDecl == null || !traceCDLoader.TraceVerbose) {
                return; 
            } 

#pragma warning disable 618 
            ICodeGenerator codeGenerator = new Microsoft.CSharp.CSharpCodeProvider().CreateGenerator();
#pragma warning restore 618
            System.IO.StringWriter sw = new System.IO.StringWriter(CultureInfo.InvariantCulture);
 
            try {
                codeGenerator.GenerateCodeFromType(typeDecl, sw, null); 
            } 
            catch (Exception ex) {
                sw.WriteLine("Error during declaration dump: " + ex.Message); 
            }

            // spit this line by line so it respects the indent.
            // 
            System.IO.StringReader sr = new System.IO.StringReader(sw.ToString());
 
            for (string ln = sr.ReadLine(); ln != null; ln = sr.ReadLine()) { 
                Debug.WriteLine(ln);
            } 
        }
#endif

        /// returns true if the given type has a root designer. 
        private bool HasRootDesignerAttribute(Type t) {
            AttributeCollection attributes = TypeDescriptor.GetAttributes(t); 
            for (int i = 0; i < attributes.Count; i++) 
            {
                DesignerAttribute da = attributes[i] as DesignerAttribute; 
                if (da != null) {
                    Type attributeBaseType = Type.GetType(da.DesignerBaseTypeName);
                    if (attributeBaseType != null && attributeBaseType == typeof(IRootDesigner)) {
                        return true; 
                    }
                } 
            } 

            return false; 
        }

        /// 
        ///     This ensures that we can load the code dom elements into a 
        ///     document.  It ensures that there is a code dom provider, that
        ///     the provider can parse the code, and that the returned 
        ///     code compile unit contains a class that can be deserialized 
        ///     through a code dom serializer.  During all of this checking
        ///     it establishes state in our member variables so that 
        ///     calls after it can assume that the variables are set.  This
        ///     will throw a human readable exception if any part of the
        ///     process fails.
        ///  
        private void EnsureDocument(IDesignerSerializationManager manager) {
 
            Debug.Assert(manager != null, "Should pass a serialization manager into EnsureDocument"); 

            // If we do not yet have the compile unit, ask for it. 
            //
            if (_documentCompileUnit == null) {
                Debug.Assert(_documentType == null && _documentNamespace == null, "We have no compile unit but we still have a type or namespace.  Our state is inconsistent.");
                _documentCompileUnit = Parse(); 
                if (_documentCompileUnit == null) {
                    Exception ex = new NotSupportedException(SR.GetString(SR.CodeDomDesignerLoaderNoLanguageSupport)); 
 
                    ex.HelpLink = SR.CodeDomDesignerLoaderNoLanguageSupport;
                    throw ex; 
                }
            }

            // Search namespaces and types to identify something that we can 
            // load.
            // 
            if (_documentType == null) { 
                // We keep track of any failures here.  If we failed to find a type this
                // array list will contain a list of strings listing what we have 
                // tried.
                //
                ArrayList failures = null;
                bool firstClass = true; 

                if(_documentCompileUnit.UserData[typeof(InvalidOperationException)] != null) { 
                    InvalidOperationException invalidOp = _documentCompileUnit.UserData[typeof(InvalidOperationException)] as InvalidOperationException; 
                    if(invalidOp != null) {
                        _documentCompileUnit = null; // not efficient but really a corner case... 
                        throw invalidOp;
                    }
                }
 
                // Look in the compile unit for a class we can load.  The first one we find
                // that has an appropriate serializer attribute, we take. 
                // 
                foreach (CodeNamespace ns in _documentCompileUnit.Namespaces) {
                    foreach (CodeTypeDeclaration typeDecl in ns.Types) { 
                        // Uncover the base type of this class.  In case we totally fail
                        // we document each time we were unable to load a particular
                        // class.
                        // 
                        Type baseType = null;
 
                        foreach (CodeTypeReference typeRef in typeDecl.BaseTypes) { 
                            Type t = LoaderHost.GetType(CodeDomSerializerBase.GetTypeNameFromCodeTypeReference(manager, typeRef));
 
                            if (t != null && !(t.IsInterface)) {
                                baseType = t;
                                break;
                            } 

                            if (t == null) { 
                                if (failures == null) { 
                                    failures = new ArrayList();
                                } 

                                failures.Add(SR.GetString(SR.CodeDomDesignerLoaderDocumentFailureTypeNotFound, typeDecl.Name, typeRef.BaseType));
                            }
                        } 

                        // We have a potential type.  The next step is to examine the type's attributes 
                        // and see if there is a root designer serializer attribute that supports the 
                        // code dom.
                        // 
                        if (baseType != null) {
                            bool foundAttribute = false;

                            // Backwards Compat:  RootDesignerSerializer is obsolete, but we need to still 
                            // be compatible and read it.
                            // Walk the member attributes for this type, looking for an appropriate serializer 
                            // attribute. 
                            //
#pragma warning disable 0618 
                            AttributeCollection attributes = TypeDescriptor.GetAttributes(baseType);
                            foreach (Attribute attr in attributes) {
                                if (attr is RootDesignerSerializerAttribute) {
 
                                    RootDesignerSerializerAttribute ra = (RootDesignerSerializerAttribute)attr;
                                    string typeName = ra.SerializerBaseTypeName; 
 
                                    // This serializer must support a CodeDomSerializer or we're not interested.
                                    // 
                                    if (typeName != null && LoaderHost.GetType(typeName) == typeof(CodeDomSerializer)) {
                                        Type serializerType = LoaderHost.GetType(ra.SerializerTypeName);

                                        if (serializerType != null && serializerType != typeof(RootCodeDomSerializer)) { 
                                            foundAttribute = true;
                                            if (firstClass) { 
                                                _rootSerializer = (CodeDomSerializer)Activator.CreateInstance(serializerType, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.CreateInstance, null, null, null); 
                                                break;
                                            } 
                                            else {
                                                throw new InvalidOperationException(SR.GetString(SR.CodeDomDesignerLoaderSerializerTypeNotFirstType, typeDecl.Name));
                                            }
                                        } 
                                    }
                                } 
                            } 
#pragma warning restore 0618
 
                            //add a check for root designer -- this allows an extra level of checking so we can skip classes
                            //that cannot be designed.
                            if (_rootSerializer == null && HasRootDesignerAttribute(baseType)) {
                                _typeSerializer = manager.GetSerializer(baseType, typeof(TypeCodeDomSerializer)) as TypeCodeDomSerializer; 
                                if (!firstClass && _typeSerializer != null) {
                                    _typeSerializer = null; 
                                    _documentCompileUnit = null; 
                                    throw new InvalidOperationException(SR.GetString(SR.CodeDomDesignerLoaderSerializerTypeNotFirstType, typeDecl.Name));
                                } 
                            }


                            // If we didn't find a serializer for this type, report it. 
                            //
                            if (_rootSerializer == null && _typeSerializer == null) { 
                                if (failures == null) { 
                                    failures = new ArrayList();
                                } 

                                if (foundAttribute) {
                                    failures.Add(SR.GetString(SR.CodeDomDesignerLoaderDocumentFailureTypeDesignerNotInstalled, typeDecl.Name, baseType.FullName));
                                } 
                                else {
                                    failures.Add(SR.GetString(SR.CodeDomDesignerLoaderDocumentFailureTypeNotDesignable, typeDecl.Name, baseType.FullName)); 
                                } 
                            }
                        } 

                        // If we found a serializer, then we're done.  Save this type and namespace for later
                        // use.
                        // 
                        if (_rootSerializer != null || _typeSerializer != null) {
                            _documentNamespace = ns; 
                            _documentType = typeDecl; 
                            break;
                        } 

                        firstClass = false;
                    }
 
                    if (_documentType != null) {
                        break; 
                    } 
                }
 
                // If we did not get a document type, throw, because we're unable to continue.
                //
                if (_documentType == null) {
                    // The entire compile unit needs to be thrown away so 
                    // we can later reparse.
                    // 
                    _documentCompileUnit = null; 

                    // Did we get any reasons why we can't load this document?  If so, synthesize a nice 
                    // description to the user.
                    //
                    Exception ex;
 
                    if (failures != null) {
                        StringBuilder builder = new StringBuilder(); 
 
                        foreach (string failure in failures) {
                            builder.Append("\r\n"); 
                            builder.Append(failure);
                        }

                        ex = new InvalidOperationException(SR.GetString(SR.CodeDomDesignerLoaderNoRootSerializerWithFailures, builder.ToString())); 
                        ex.HelpLink = SR.CodeDomDesignerLoaderNoRootSerializer;
                    } 
                    else { 
                        ex = new InvalidOperationException(SR.GetString(SR.CodeDomDesignerLoaderNoRootSerializer));
                        ex.HelpLink = SR.CodeDomDesignerLoaderNoRootSerializer; 
                    }

                    throw ex;
                } 
                else {
                    // We are successful.  At this point, we want to provide some of these 
                    // code dom elements as services for outside parties to use. 
                    //
                    LoaderHost.AddService(typeof(CodeTypeDeclaration), _documentType); 
                }
            }
            codemarkers.CodeMarker(CodeMarkerEvent.perfFXGetDocumentType);
        } 

        ///  
        ///     Takes the given code element and integrates it into the existing CodeDom 
        ///     tree stored in _documentCompileUnit.  This returns true if any changes
        ///     were made to the tree. 
        /// 
        private bool IntegrateSerializedTree(IDesignerSerializationManager manager, CodeTypeDeclaration newDecl) {
            EnsureDocument(manager);
 
            CodeTypeDeclaration docDecl = _documentType;
            bool caseInsensitive = false; 
            bool codeDomDirty = false; 
            CodeDomProvider provider = CodeDomProvider;
 
            if (provider != null) {
                caseInsensitive = ((provider.LanguageOptions & LanguageOptions.CaseInsensitive) != 0);
            }
 
            // Update the class name of the code type, in case it is different.
            // 
            if (!string.Equals(docDecl.Name, newDecl.Name, caseInsensitive ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal)) { 
                docDecl.Name = newDecl.Name;
                codeDomDirty = true; 
            }

            if (!docDecl.Attributes.Equals(newDecl.Attributes)) {
                docDecl.Attributes = newDecl.Attributes; 
                codeDomDirty = true;
            } 
 
            // Now, hash up the member names in the document and use this
            // when determining what to add and what to replace.  In addition, 
            // we also build up a set of indexes into approximate locations for
            // inserting fields and methods.
            //
            int fieldInsertLocation = 0; 
            bool lockField = false;
            int methodInsertLocation = 0; 
            bool lockMethod = false; 
            IDictionary docMemberHash = new HybridDictionary(docDecl.Members.Count, caseInsensitive);
            int memberCount = docDecl.Members.Count; 

            for (int i = 0; i < memberCount; i++) {
                CodeTypeMember member = docDecl.Members[i];
                string memberName; 

                if (member is CodeConstructor) { 
                    memberName = ".ctor"; 
                }
                else if (member is CodeTypeConstructor) { 
                    memberName = ".cctor";
                }
                else {
                    memberName = member.Name; 
                }
 
                docMemberHash[memberName] = i; 
                if (member is CodeMemberField) {
                    if (!lockField) { 
                        fieldInsertLocation = i;
                    }
                }
                else { 
                    if (fieldInsertLocation > 0) {
                        lockField = true; 
                    } 
                }
 
                if (member is CodeMemberMethod) {
                    if (!lockMethod) {
                        methodInsertLocation = i;
                    } 
                }
                else { 
                    if (methodInsertLocation > 0) { 
                        lockMethod = true;
                    } 
                }
            }

            // Now start looking through the new declaration and process it. 
            // We are index driven, so if we need to add new values we put
            // them into an array list, and post process them. 
            // 
            ArrayList newElements = new ArrayList();
 
            foreach (CodeTypeMember member in newDecl.Members) {
                string memberName;

                if (member is CodeConstructor) { 
                    memberName = ".ctor";
                } 
                else { 
                    memberName = member.Name;
                } 

                object existingSlot = docMemberHash[memberName];

                if (existingSlot != null) { 
                    int slot = (int)existingSlot;
                    CodeTypeMember existingMember = docDecl.Members[slot]; 
 
                    if (existingMember == member) {
                        continue; 
                    }

                    if (member is CodeMemberField) {
                        if (existingMember is CodeMemberField) { 
                            CodeMemberField docField = (CodeMemberField)existingMember;
                            CodeMemberField newField = (CodeMemberField)member; 
 
                            // We will be case-sensitive always in working out whether to replace the field
                            if ((string.Equals(newField.Name, docField.Name)) && newField.Attributes == docField.Attributes && TypesEqual(newField.Type, docField.Type)) { 
                                continue;
                            }
                            else {
                                docDecl.Members[slot] = member; 
                            }
                        } 
                        else { 
                            // We adding a field with the same name as a method. This should cause a
                            // compile error, but we don't want to clobber the existing method. 
                            newElements.Add(member);
                        }
                    }
                    else if (member is CodeMemberMethod) { 
                        if (existingMember is CodeMemberMethod) {
                            // If there is an existing constructor, preserve it. 
                            if (!(existingMember is CodeConstructor)) { 
                                // For methods, we do not want to replace the method; rather, we
                                // just want to replace its contents.  This helps to preserve 
                                // the layout of the file.
                                //
                                CodeMemberMethod existingMethod = (CodeMemberMethod)existingMember;
                                CodeMemberMethod newMethod = (CodeMemberMethod)member; 

                                existingMethod.Statements.Clear(); 
                                existingMethod.Statements.AddRange(newMethod.Statements); 
                            }
                        } 
                    }
                    else {
                        docDecl.Members[slot] = member;
                    } 

                    codeDomDirty = true; 
                } 
                else {
                    newElements.Add(member); 
                }
            }

            // Now, process all new elements. 
            //
            foreach (CodeTypeMember member in newElements) { 
                if (member is CodeMemberField) { 
                    if (fieldInsertLocation >= docDecl.Members.Count) {
                        docDecl.Members.Add(member); 
                    }
                    else {
                        docDecl.Members.Insert(fieldInsertLocation, member);
                    } 

                    fieldInsertLocation++; 
                    methodInsertLocation++; 
                    codeDomDirty = true;
                } 
                else if (member is CodeMemberMethod) {
                    if (methodInsertLocation >= docDecl.Members.Count) {
                        docDecl.Members.Add(member);
                    } 
                    else {
                        docDecl.Members.Insert(methodInsertLocation, member); 
                    } 

                    methodInsertLocation++; 
                    codeDomDirty = true;
                }
                else {
                    // For rare members, just add them to the end. 
                    //
                    docDecl.Members.Add(member); 
                    codeDomDirty = true; 
                }
            } 

            return codeDomDirty;
        }
 
        /// 
        ///  
        ///     This method is called immediately after the first time 
        ///     BeginLoad is invoked.  This is an appopriate place to
        ///     add custom services to the loader host.  Remember to 
        ///     remove any custom services you add here by overriding
        ///     Dispose.
        /// 
        protected override void Initialize() { 
            base.Initialize();
 
            ServiceCreatorCallback callback = new ServiceCreatorCallback(OnCreateService); 

            LoaderHost.AddService(typeof(ComponentSerializationService), callback); 
            LoaderHost.AddService(typeof(INameCreationService), this);
            LoaderHost.AddService(typeof(IDesignerSerializationService), this);

            // The code dom desinger loader requires a working ITypeResolutionService to 
            // function.  See if someone added one already, and if not, provide
            // our own. 
            if (GetService(typeof(ITypeResolutionService)) == null) { 
                ITypeResolutionService trs = TypeResolutionService;
                if (trs == null) { 
                    throw new InvalidOperationException(SR.GetString(SR.CodeDomDesignerLoaderNoTypeResolution));
                }

                LoaderHost.AddService(typeof(ITypeResolutionService), trs); 
                _state[StateOwnTypeResolution] = true;
            } 
 
            _extenderProviderService = GetService(typeof(IExtenderProviderService)) as IExtenderProviderService;
            if (_extenderProviderService != null) { 
                _extenderProviders = new IExtenderProvider[] {
                    new ModifiersExtenderProvider(),
                    new ModifiersInheritedExtenderProvider()
                }; 
                foreach (IExtenderProvider p in _extenderProviders) {
                    _extenderProviderService.AddExtenderProvider(p); 
                } 
            }
        } 

        /// 
        /// 
        ///     Determines if the designer needs to be reloaded.  It does this 
        ///     by examining the code dom tree for changes.  This does not check
        ///     for outside infleuences; the caller should already think a reload 
        ///     is needed -- this is just a last optimization. 
        /// 
        protected override bool IsReloadNeeded() { 
            if (!base.IsReloadNeeded()) {
                return false;
            }
 
            // If we have no document, we definitely need a reload.
            // 
            if (_documentType == null) { 
                return true;
            } 

            // If we can't get to a code dom provider, or if that provider doesn't
            // implement ICodeDomDesignerReload, we can't optimize the reload, so we
            // just assume it is needed. 
            //
            ICodeDomDesignerReload reloader = CodeDomProvider as ICodeDomDesignerReload; 
 
            if (reloader == null) {
                return true; 
            }

            bool reload = true;
 
            // Parse the file and see if we actually need to reload.
            // 
            string oldTypeName = _documentType.Name; 

            // StartTimingMark(); 
            try {
                ClearDocument();
                EnsureDocument(GetService(typeof(IDesignerSerializationManager)) as IDesignerSerializationManager);
            } 
            catch {
                // If the document is not in a state where we can get any information 
                // from it, we will assume this is a reload.  The error will then 
                // be displayed to the user when the designer does actually
                // reload. 
            }

            // EndTimingMark("Reload Parse I");
            if (_documentCompileUnit != null) { 
                reload = reloader.ShouldReloadDesigner(_documentCompileUnit);
                reload |= (_documentType == null || !_documentType.Name.Equals(oldTypeName)); 
            } 

            return reload; 
        }

        /// 
        ///  
        ///     This method should be called by the designer loader service
        ///     when the first dependent load has started.  This initializes 
        ///     the state of the code dom loader and prepares it for loading. 
        ///     By default, the designer loader provides
        ///     IDesignerLoaderService itself, so this is called automatically. 
        ///     If you provide your own loader service, or if you choose not
        ///     to provide a loader service, you are responsible for calling
        ///     this method.  BeginLoad will automatically call this, either
        ///     indirectly by calling AddLoadDependency if IDesignerLoaderService 
        ///     is available, or directly if it is not.
        ///  
        protected override void OnBeginLoad() { 
            // Make sure that we're removed any event sinks we added after we finished the load.
            // 
            IComponentChangeService cs = (IComponentChangeService)GetService(typeof(IComponentChangeService));

            if (cs != null) {
                cs.ComponentRemoved -= new ComponentEventHandler(this.OnComponentRemoved); 
                cs.ComponentRename -= new ComponentRenameEventHandler(OnComponentRename);
            } 
 
            base.OnBeginLoad();
        } 

        /// 
        /// 
        ///     This method is called immediately before the document is unloaded. 
        ///     The document may be unloaded in preparation for reload, or
        ///     if the document failed the load.  If you added document-specific 
        ///     services in OnBeginLoad or OnEndLoad, you should remove them 
        ///     here.
        ///  
        protected override void OnBeginUnload() {
            base.OnBeginUnload();
            ClearDocument();
        } 

        ///  
        ///     This is called whenever a component is removed from the design surface. 
        /// 
        private void OnComponentRemoved(object sender, ComponentEventArgs e) { 
            string name = e.Component.Site.Name;
            RemoveDeclaration(name);
        }
 
        /// 
        ///     Raised by the host when a component is renamed.  Here we dirty ourselves 
        ///     and then whack the component declaration.  At the next code gen 
        ///     cycle we will recreate the declaration.
        ///  
        private void OnComponentRename(object sender, ComponentRenameEventArgs e) {
            OnComponentRename(e.Component, e.OldName, e.NewName);
        }
 
        /// 
        ///     Callback to create our demand-created services. 
        ///  
        private object OnCreateService(IServiceContainer container, Type serviceType) {
            if (serviceType == typeof(ComponentSerializationService)) { 
                return new CodeDomComponentSerializationService(LoaderHost);
            }

            Debug.Fail("Called to create unknown service."); 
            return null;
        } 
 
        /// 
        ///  
        ///     This method should be called by the designer loader service
        ///     when all dependent loads have been completed.  This
        ///     "shuts down" the loading process that was initiated by
        ///     BeginLoad.  By default, the designer loader provides 
        ///     IDesignerLoaderService itself, so this is called automatically.
        ///     If you provide your own loader service, or if you choose not 
        ///     to provide a loader service, you are responsible for calling 
        ///     this method.  BeginLoad will automatically call this, either
        ///     indirectly by calling DependentLoadComplete if IDesignerLoaderService 
        ///     is available, or directly if it is not.
        /// 
        protected override void OnEndLoad(bool successful, ICollection errors) {
            base.OnEndLoad(successful, errors); 
            if (successful) {
                // After a successful load we will want to monitor a bunch of events so we know when 
                // to make the loader dirty. 
                //
                IComponentChangeService cs = (IComponentChangeService)GetService(typeof(IComponentChangeService)); 

                if (cs != null) {
                    cs.ComponentRemoved += new ComponentEventHandler(this.OnComponentRemoved);
                    cs.ComponentRename += new ComponentRenameEventHandler(OnComponentRename); 
                }
            } 
        } 

        ///  
        /// 
        ///     This abstract method is called when it is time to
        ///     parse the source code and create a CodeDom tree.
        ///  
        protected abstract CodeCompileUnit Parse();
 
        ///  
        /// 
        ///     Overrides BasicDesignerLoader's PerformFlush method to actual 
        ///     write out the code dom tree.
        /// 
        protected override void PerformFlush(IDesignerSerializationManager manager) {
            CodeTypeDeclaration typeDecl = null; 

            // Ask the serializer for the root component to serialize.  This should return 
            // a CodeTypeDeclaration, which we will plug into our existing code DOM tree. 
            //
            Debug.Assert(_rootSerializer != null || _typeSerializer != null, "What are we saving right now?  Base component has no serializer: " + LoaderHost.RootComponent.GetType().FullName); 
            if (_rootSerializer != null) {
                typeDecl = _rootSerializer.Serialize(manager, LoaderHost.RootComponent) as CodeTypeDeclaration;
                Debug.Assert(typeDecl != null, "Root CodeDom serializer must return a CodeTypeDeclaration");
            } 
            else if (_typeSerializer != null) {
                typeDecl = _typeSerializer.Serialize(manager, LoaderHost.RootComponent, LoaderHost.Container.Components); 
            } 

#if DEBUG 
            if (traceCDLoader.TraceVerbose) {
                Debug.WriteLine("****************** Pre-integrated tree **********************");
                DumpTypeDeclaration(typeDecl);
                EnsureDocument(manager); 
                Debug.WriteLine("****************** Live tree **********************");
                DumpTypeDeclaration(_documentType); 
            } 
#endif
            codemarkers.CodeMarker(CodeMarkerEvent.perfFXGenerateCodeTreeEnd); 

            // Now we must integrate the code DOM tree from the serializer with
            // our own tree.  If changes were made to the tree this will
            // return true. 
            //
            if (typeDecl != null && IntegrateSerializedTree(manager, typeDecl)) { 
                codemarkers.CodeMarker(CodeMarkerEvent.perfFXIntegrateSerializedTreeEnd); 
#if DEBUG
                if (traceCDLoader.TraceVerbose) { 
                    Debug.WriteLine("****************** Integrated tree **********************");
                    DumpTypeDeclaration(_documentType);
                }
#endif 

                // EndTimingMark("Serialize tree"); 
                // StartTimingMark(); 
                Write(_documentCompileUnit);
                // EndTimingMark("Generate unit total"); 
            }
            else {
                Debug.WriteLineIf(traceCDLoader.TraceVerbose, "No need to integrate tree; no changes detected");
            } 
        }
 
        ///  
        /// 
        ///     Overrides BasicDesignerLoader's PerformLoad method to deserialize the 
        ///     classes from the code dom.
        /// 
        protected override void PerformLoad(IDesignerSerializationManager manager) {
            // This ensures that all of the state for the document is available.  This 
            // will throw if state we need to load cannot be obtained.
            // 
            EnsureDocument(manager); 

            // Ok, now we have a document, and a root serializer and a namespace.  Or, 
            // at least we better.
            Debug.Assert(_documentType != null, "EnsureDocument didn't create a document type");
            Debug.Assert(_documentNamespace != null, "EnsureDocument didn't create a document namespace");
            Debug.Assert(_rootSerializer != null || _typeSerializer != null, "EnsureDocument didn't create a root serializer"); 

            // StartTimingMark(); 
            codemarkers.CodeMarker(CodeMarkerEvent.perfFXDeserializeStart); 
            if (_rootSerializer != null) {
                _rootSerializer.Deserialize(manager, _documentType); 
            }
            else {
                _typeSerializer.Deserialize(manager, _documentType);
            } 
            codemarkers.CodeMarker(CodeMarkerEvent.perfFXDeserializeEnd);
 
            // EndTimingMark("Deserialize document"); 
            string baseComp = string.Format(CultureInfo.CurrentCulture, "{0}.{1}", _documentNamespace.Name, _documentType.Name);
 
            SetBaseComponentClassName(baseComp);
        }

        ///  
        /// 
        ///     This virtual method gets override in the VsCodeDomDesignerLoader to call the RenameElement on the 
        ///     ChangeNotificationService to rename the component name through out the project scope. 
        /// 
        protected virtual void OnComponentRename(object component, string oldName, string newName) 
        {
            if (LoaderHost.RootComponent == component) {
                if (_documentType != null) {
                    _documentType.Name = newName; 
                }
            } else { 
                if (_documentType != null) { 
                    CodeTypeMemberCollection members = _documentType.Members;
 
                    for (int i = 0; i < members.Count; i++) {
                        if (members[i] is CodeMemberField
                                && members[i].Name.Equals(oldName)
                                && ((CodeMemberField)members[i]).Type.BaseType.Equals(TypeDescriptor.GetClassName(component))) { 
                            members[i].Name = newName;
                            break; 
                        } 
                    }
                } 
            }
        }

        ///  
        ///     This is called when a component is deleted or renamed.  We remove
        ///     the component's declaration here, if it exists. 
        ///  
        private void RemoveDeclaration(string name) {
            if (_documentType != null) { 
                CodeTypeMemberCollection members = _documentType.Members;

                for (int i = 0; i < members.Count; i++) {
                    if (members[i] is CodeMemberField && members[i].Name.Equals(name)) { 
                        ((IList)members).RemoveAt(i);
                        break; 
                    } 
                }
            } 
        }

        /// 
        ///     Simple helper routine that will throw an exception if we need a service, but cannot get 
        ///     to it.  You should only throw for missing services that are absolutely essential for
        ///     operation.  If there is a way to gracefully degrade, then you should do it. 
        ///  
        private void ThrowMissingService(Type serviceType) {
            Exception ex = new InvalidOperationException(SR.GetString(SR.BasicDesignerLoaderMissingService, serviceType.Name)); 

            ex.HelpLink = SR.BasicDesignerLoaderMissingService;
            throw ex;
        } 

        ///  
        ///    Determines of two type references are equal. 
        /// 
        private static bool TypesEqual(CodeTypeReference typeLeft, CodeTypeReference typeRight) { 
            if (typeLeft.ArrayRank != typeRight.ArrayRank) return false;

            if (!typeLeft.BaseType.Equals(typeRight.BaseType)) return false;
 
            if (typeLeft.TypeArguments != null && typeRight.TypeArguments == null) return false;
            if (typeLeft.TypeArguments == null && typeRight.TypeArguments != null) return false; 
 
            if (typeLeft.TypeArguments != null && typeRight.TypeArguments != null) {
                if (typeLeft.TypeArguments.Count != typeRight.TypeArguments.Count) return false; 
                for (int i = 0; i < typeLeft.TypeArguments.Count; i++) {
                    if (!TypesEqual(typeLeft.TypeArguments[i], typeRight.TypeArguments[i])) return false;
                }
            } 

            if (typeLeft.ArrayRank > 0) { 
                return TypesEqual(typeLeft.ArrayElementType, typeRight.ArrayElementType); 
            }
 
            return true;
        }

        ///  
        /// 
        ///     This abstract method is called in response to a Flush 
        ///     call when the designer loader is dirty.  It will pass 
        ///     a new CodeCompileUnit that represents the source code
        ///     needed to recreate the current designer's component 
        ///     graph.
        /// 
        protected abstract void Write(CodeCompileUnit unit);
 
        /// 
        ///  
        ///     Deserializes the provided serialization data object and 
        ///     returns a collection of objects contained within that
        ///     data. 
        /// 
        ICollection IDesignerSerializationService.Deserialize(object serializationData) {
            if (!(serializationData is SerializationStore)) {
                Exception ex = new ArgumentException(SR.GetString(SR.CodeDomDesignerLoaderBadSerializationObject)); 

                ex.HelpLink = SR.CodeDomDesignerLoaderBadSerializationObject; 
                throw ex; 
            }
 
            ComponentSerializationService css = GetService(typeof(ComponentSerializationService)) as ComponentSerializationService;

            if (css == null) {
                ThrowMissingService(typeof(ComponentSerializationService)); 
            }
 
            return css.Deserialize((SerializationStore)serializationData, LoaderHost.Container); 
        }
 
        /// 
        /// 
        ///     Serializes the given collection of objects and
        ///     stores them in an opaque serialization data object. 
        ///     The returning object fully supports runtime serialization.
        ///  
        object IDesignerSerializationService.Serialize(ICollection objects) { 
            if (objects == null) {
                objects = new object[0]; 
            }

            ComponentSerializationService css = GetService(typeof(ComponentSerializationService)) as ComponentSerializationService;
 
            if (css == null) {
                ThrowMissingService(typeof(ComponentSerializationService)); 
            } 

            SerializationStore store = css.CreateStore(); 

            using (store) {
                foreach (object o in objects) {
                    css.Serialize(store, o); 
                }
            } 
 
            return store;
        } 

        /// 
        /// 
        ///     Creates a new name that is unique to all the components 
        ///     in the given container.  The name will be used to create
        ///     an object of the given data type, so the service may 
        ///     derive a name from the data type's name. 
        /// 
        string INameCreationService.CreateName(IContainer container, Type dataType) { 
            if (dataType == null) {
                throw new ArgumentNullException("dataType");
            }
 
            string finalName;
            string baseName = dataType.Name; 
 
            // Create a base member name that is a camel casing of the
            // data type name. 
            //
            StringBuilder b = new StringBuilder(baseName.Length);

            for (int i = 0; i < baseName.Length; i++) { 
                if (Char.IsUpper(baseName[i]) && (i == 0 || i == baseName.Length - 1 || Char.IsUpper(baseName[i + 1]))) {
                    b.Append(Char.ToLower(baseName[i], CultureInfo.CurrentCulture)); 
                } 
                else {
                    b.Append(baseName.Substring(i)); 
                    break;
                }
            }
 
            b.Replace('`', '_');
 
            baseName = b.ToString(); 

            // Now hash up all of the member variable names using a case insensitve hash. 
            //
            CodeTypeDeclaration type = _documentType;
            Hashtable memberHash = new Hashtable(StringComparer.CurrentCultureIgnoreCase);
 
            if (type != null) {
                foreach (CodeTypeMember member in type.Members) { 
                    memberHash[member.Name] = member; 
                }
            } 

            // VSWhidbey 95065: Only attempt to build a unique name here if we have a valid container
            // against which to check the result. Otherwise, the name build here might be appended to
            // with yet another iterator elsewhere. FWIW, this check is identical to the check used in 
            // BaseDesignerLoader's implementation of INameCreationService.CreateName().
            if (container != null) { 
                int idx = 0; 
                bool conflict;
 
                // Now loop until we find a name that hasn't been used.
                //
                do {
                    idx++; 
                    conflict = false;
                    finalName = string.Format(CultureInfo.CurrentCulture, "{0}{1}", baseName, idx.ToString(CultureInfo.InvariantCulture)); 
 
                    if (container != null && container.Components[finalName] != null) {
                        conflict = true; 
                    }
                    if (!conflict && memberHash[finalName] != null) {
                        conflict = true;
                    } 

                } while (conflict); 
            } 
            else {
                finalName = baseName; 
            }

            // And validate the new name against the code dom's code
            // generator to ensure it's not a keyword. 
            //
            if (_codeGenerator == null) { 
                CodeDomProvider provider = CodeDomProvider; 

                if (provider != null) { 
#pragma warning disable 618
                    _codeGenerator = provider.CreateGenerator();
#pragma warning restore 618
                } 
            }
 
            if (_codeGenerator != null) { 
                finalName = _codeGenerator.CreateValidIdentifier(finalName);
            } 

            return finalName;
        }
 
        /// 
        ///  
        ///     Determines if the given name is valid.  A name 
        ///     creation service may have rules defining a valid
        ///     name, and this method allows the sevice to enforce 
        ///     those rules.
        /// 
        bool INameCreationService.IsValidName(string name) {
            if (name == null) { 
                throw new ArgumentNullException("name");
            } 
 
            if (name.Length == 0) {
                return false; 
            }

            if (_codeGenerator == null) {
                CodeDomProvider provider = CodeDomProvider; 

                if (provider != null) { 
#pragma warning disable 618 
                    _codeGenerator = provider.CreateGenerator();
#pragma warning restore 618 
                }
            }

            if (_codeGenerator != null) { 
                if (!_codeGenerator.IsValidIdentifier(name)) {
                    return false; 
                } 

                if (!_codeGenerator.IsValidIdentifier(name + "Handler")) { 
                    return false;
                }
            }
 
            // We don't validate against the type members if we're loading,
            // because during load these members are being added by the 
            // parser, so of course there will be duplicates. 
            if (!Loading) {
                CodeTypeDeclaration type = _documentType; 

                if (type != null) {
                    foreach (CodeTypeMember member in type.Members) {
                        if (string.Equals(member.Name, name, StringComparison.OrdinalIgnoreCase)) { 
                            return false;
                        } 
                    } 
                }
 
                // If the designer has been modified there is a chance that
                // the document type does not have all the necessary
                // members in it yet.  So, we need to check the container
                // as well. 
                if (Modified && LoaderHost.Container.Components[name] != null) {
                    return false; 
                } 
            }
 
            return true;
        }

        ///  
        /// 
        ///     Determines if the given name is valid.  A name 
        ///     creation service may have rules defining a valid 
        ///     name, and this method allows the sevice to enforce
        ///     those rules.  It is similar to IsValidName, except 
        ///     that this method will throw an exception if the
        ///     name is invalid.  This allows implementors to provide
        ///     rich information in the exception message.
        ///  
        void INameCreationService.ValidateName(string name) {
            if (name == null) { 
                throw new ArgumentNullException("name"); 
            }
 
            if (name.Length == 0) {
                Exception ex = new ArgumentException(SR.GetString(SR.CodeDomDesignerLoaderInvalidBlankIdentifier));

                ex.HelpLink = SR.CodeDomDesignerLoaderInvalidIdentifier; 
                throw ex;
            } 
 
            if (_codeGenerator == null) {
                CodeDomProvider provider = CodeDomProvider; 

                if (provider != null) {
#pragma warning disable 618
                    _codeGenerator = provider.CreateGenerator(); 
#pragma warning restore 618
                } 
            } 

            if (_codeGenerator != null) { 
                _codeGenerator.ValidateIdentifier(name);
                try {
                    // We add something arbitrary and try to validate that. This is because we want to make sure
                    // adding something is going to be fine, if not our event handler name generation will break in 
                    // case this identifier is something like a VB escaped keyword. For example, [public] is fine
                    // but [public]_Click is not. 
                    _codeGenerator.ValidateIdentifier(name + "_"); 
                }
                catch { 
                    // we have to change the exception back to the original name
                    Exception ex = new ArgumentException(SR.GetString(SR.CodeDomDesignerLoaderInvalidIdentifier, name));

                    ex.HelpLink = SR.CodeDomDesignerLoaderInvalidIdentifier; 
                    throw ex;
                } 
            } 

            // We don't validate against the type members if we're loading, 
            // because during load these members are being added by the
            // parser, so of course there will be duplicates.
            if (!Loading) {
                bool dup = false; 
                CodeTypeDeclaration type = _documentType;
 
                if (type != null) { 
                    foreach (CodeTypeMember member in type.Members) {
                        if (string.Equals(member.Name, name, StringComparison.OrdinalIgnoreCase)) { 
                            dup = true;
                            break;
                        }
                    } 
                }
 
                // If the designer has been modified there is a chance that 
                // the document type does not have all the necessary
                // members in it yet.  So, we need to check the container 
                // as well.
                if (!dup && Modified && LoaderHost.Container.Components[name] != null) {
                    dup = true;
                } 

                if (dup) { 
                    Exception ex = new ArgumentException(SR.GetString(SR.CodeDomDesignerLoaderDupComponentName, name)); 

                    ex.HelpLink = SR.CodeDomDesignerLoaderDupComponentName; 
                    throw ex;
                }
            }
        } 

        ///  
        ///      This extender provider provides the "Modifiers" property. 
        /// 
        [ProvideProperty("Modifiers", typeof(IComponent))] 
        [ProvideProperty("GenerateMember", typeof(IComponent))]
        private class ModifiersExtenderProvider : IExtenderProvider {
            private IDesignerHost _host;
 
            /// 
            ///     Determines if ths extender provider can extend the given object.  We extend 
            ///     all objects, so we always return true. 
            /// 
            public bool CanExtend(object o) { 
                IComponent c = o as IComponent;

                if (c == null) {
                    return false; 
                }
 
                // We don't add modifiers to the base component. 
                //
                IComponent baseComponent = GetBaseComponent(c); 

                if (o == baseComponent) {
                    return false;
                } 

                // Now see if this object is inherited.  If so, then we don't want to 
                // extend. 
                //
                if (!TypeDescriptor.GetAttributes(o)[typeof(InheritanceAttribute)].Equals(InheritanceAttribute.NotInherited)) { 
                    return false;
                }

                return true; 
            }
 
            private IComponent GetBaseComponent(IComponent c) { 
                IComponent baseComponent = null;
 
                if (c == null) {
                    return null;
                }
 
                if (_host == null) {
                    ISite site = c.Site; 
                    if (site != null) { 
                        _host = (IDesignerHost)site.GetService(typeof(IDesignerHost));
                    } 
                }

                if (_host != null) {
                    baseComponent = _host.RootComponent; 
                }
 
                return baseComponent; 
            }
 
            /// 
            ///     This is an extender property that we offer to all components
            ///     on the form.  It implements the "GenerateMember" property, which
            ///     is a boolean that, if true, causes a field member to be generated for 
            ///     the object.
            ///  
            [DesignOnly(true), DefaultValue(true), SRDescription(SR.CodeDomDesignerLoaderPropGenerateMember), Category("Design")] 
            [HelpKeyword("Designer_GenerateMember")]
            public bool GetGenerateMember(IComponent comp) { 
                ISite site = comp.Site;

                if (site != null) {
                    IDictionaryService dictionary = (IDictionaryService)site.GetService(typeof(IDictionaryService)); 

                    if (dictionary != null) { 
                        object value = dictionary.GetValue("GenerateMember"); 

                        if (value is bool) { 
                            return (bool)value;
                        }
                    }
 
                }
 
                return true; 
            }
 
            /// 
            ///     This is an extender property that we offer to all components
            ///     on the form.  It implements the "Modifiers" property, which
            ///     is an enum represneing the "public/protected/private" scope 
            ///     of a component.
            ///  
            [DesignOnly(true), TypeConverter(typeof(ModifierConverter)), DefaultValue(MemberAttributes.Private), SRDescription(SR.CodeDomDesignerLoaderPropModifiers), Category("Design")] 
            [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
            [HelpKeyword("Designer_Modifiers")] 
            public MemberAttributes GetModifiers(IComponent comp) {
                ISite site = comp.Site;

                if (site != null) { 
                    IDictionaryService dictionary = (IDictionaryService)site.GetService(typeof(IDictionaryService));
 
                    if (dictionary != null) { 
                        object value = dictionary.GetValue("Modifiers");
 
                        if (value is MemberAttributes) {
                            return (MemberAttributes)value;
                        }
                    } 
                }
 
                // Check to see if someone offered up a "DefaultModifiers" property so we can 
                // decide a default.
                // 
                PropertyDescriptorCollection props = TypeDescriptor.GetProperties(comp);
                PropertyDescriptor prop = props["DefaultModifiers"];

                if (prop != null && prop.PropertyType == typeof(MemberAttributes)) { 
                    return (MemberAttributes)prop.GetValue(comp);
                } 
 
                return MemberAttributes.Private;
            } 

            /// 
            ///     This is an extender property that we offer to all components
            ///     on the form.  It implements the "GenerateMember" property, which 
            ///     is a boolean that, if true, causes a field member to be generated for
            ///     the object. 
            ///  
            public void SetGenerateMember(IComponent comp, bool generate) {
                ISite site = comp.Site; 

                if (site != null) {
                    IDictionaryService dictionary = (IDictionaryService)site.GetService(typeof(IDictionaryService));
                    bool oldValue = GetGenerateMember(comp); 

                    if (dictionary != null) { 
                        dictionary.SetValue("GenerateMember", generate); 
                    }
 
                    // If the old value was true and the new value is false, we've got
                    // to remove the existing member declaration for this
                    // component
                    if (oldValue && !generate) { 
                        CodeTypeDeclaration typeDecl = site.GetService(typeof(CodeTypeDeclaration)) as CodeTypeDeclaration;
                        string compName = site.Name; 
 
                        if (typeDecl != null && compName != null) {
                            foreach (CodeTypeMember member in typeDecl.Members) { 
                                CodeMemberField field = member as CodeMemberField;

                                if (field != null && field.Name.Equals(compName)) {
                                    typeDecl.Members.Remove(field); 
                                    break;
                                } 
                            } 
                        }
                    } 
                }
            }

            ///  
            ///     This is an extender property that we offer to all components
            ///     on the form.  It implements the "Modifiers" property, which 
            ///     is an enum represneing the "public/protected/private" scope 
            ///     of a component.
            ///  
            public void SetModifiers(IComponent comp, MemberAttributes modifiers) {
                ISite site = comp.Site;

                if (site != null) { 
                    IDictionaryService dictionary = (IDictionaryService)site.GetService(typeof(IDictionaryService));
 
                    if (dictionary != null) { 
                        dictionary.SetValue("Modifiers", modifiers);
                    } 
                }
            }
        }
 
        /// 
        ///      This extender provider offers up read-only versions of 
        ///      "Modifiers" for inherited components. 
        /// 
        [ProvideProperty("Modifiers", typeof(IComponent))] 
        private class ModifiersInheritedExtenderProvider : IExtenderProvider {
            private IDesignerHost _host;

            ///  
            ///     Determines if ths extender provider can extend the given object.  We extend
            ///     all objects, so we always return true. 
            ///  
            public bool CanExtend(object o) {
                IComponent c = o as IComponent; 

                if (c == null) {
                    return false;
                } 

                // We don't add modifiers to the base component. 
                // 
                IComponent baseComponent = GetBaseComponent(c);
 
                if (o == baseComponent) {
                    return false;
                }
 
                // Now see if this object is inherited.  If so, then we are interested in it.
                // 
                AttributeCollection attributes = TypeDescriptor.GetAttributes(o); 

                if (!attributes[typeof(InheritanceAttribute)].Equals(InheritanceAttribute.NotInherited)) { 
                    return true;
                }

                return false; 
            }
 
            private IComponent GetBaseComponent(IComponent c) { 
                IComponent baseComponent = null;
 
                if (c == null) {
                    return null;
                }
 
                if (_host == null) {
                    ISite site = c.Site; 
                    if (site != null) { 
                        _host = (IDesignerHost)site.GetService(typeof(IDesignerHost));
                    } 
                }

                if (_host != null) {
                    baseComponent = _host.RootComponent; 
                }
 
                return baseComponent; 
            }
 
            /// 
            ///     This is an extender property that we offer to all components
            ///     on the form.  It implements the "Modifiers" property, which
            ///     is an enum represneing the "public/protected/private" scope 
            ///     of a component.
            ///  
            [DesignOnly(true), TypeConverter(typeof(ModifierConverter)), DefaultValue(MemberAttributes.Private), SRDescription(SR.CodeDomDesignerLoaderPropModifiers), Category("Design")] 
            [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
            public MemberAttributes GetModifiers(IComponent comp) { 
                IComponent baseComponent = GetBaseComponent(comp);

                Debug.Assert(baseComponent != null, "Root component was null");
 
                Type baseType = baseComponent.GetType();
                ISite site = comp.Site; 
 
                if (site != null) {
                    string name = site.Name; 

                    if (name != null) {
                        FieldInfo field = TypeDescriptor.GetReflectionType(baseType).GetField(name, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);
 
                        if (field != null) {
                            if (field.IsPrivate) return MemberAttributes.Private; 
 
                            if (field.IsPublic) return MemberAttributes.Public;
 
                            if (field.IsFamily) return MemberAttributes.Family;

                            if (field.IsAssembly) return MemberAttributes.Assembly;
 
                            if (field.IsFamilyOrAssembly) return MemberAttributes.FamilyOrAssembly;
 
                            if (field.IsFamilyAndAssembly) return MemberAttributes.FamilyAndAssembly; 
                        }
                        else { 
                            // Visual Basic uses a property called Foo and generates a field called _Foo. We need to check the
                            // visibility of this accessor to fix the modifiers up.
                            //
                            PropertyInfo prop = TypeDescriptor.GetReflectionType(baseType).GetProperty(name, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static); 

                            if (prop != null) { 
                                MethodInfo[] accessors = prop.GetAccessors(true); 

                                if (accessors != null && accessors.Length > 0) { 
                                    MethodInfo mi = accessors[0];

                                    if (mi != null) {
                                        if (mi.IsPrivate) return MemberAttributes.Private; 

                                        if (mi.IsPublic) return MemberAttributes.Public; 
 
                                        if (mi.IsFamily) return MemberAttributes.Family;
 
                                        if (mi.IsAssembly) return MemberAttributes.Assembly;

                                        if (mi.IsFamilyOrAssembly) return MemberAttributes.FamilyOrAssembly;
 
                                        if (mi.IsFamilyAndAssembly) return MemberAttributes.FamilyAndAssembly;
                                    } 
                                } 
                            }
                        } 
                    }
                }

                return MemberAttributes.Private; 
            }
        } 
 
        private class ModifierConverter : TypeConverter {
            ///  
            ///    Gets a value indicating whether this converter can
            ///       convert an object in the given source type to the native type of the converter
            ///       using the context.
            ///  
            public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) {
                return GetConverter(context).CanConvertFrom(context, sourceType); 
            } 

            ///  
            ///    Gets a value indicating whether this converter can
            ///       convert an object to the given destination type using the context.
            /// 
            public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) { 
                return GetConverter(context).CanConvertTo(context, destinationType);
            } 
 
            /// 
            ///    Converts the given object to the converter's native type. 
            /// 
            public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) {
                return GetConverter(context).ConvertFrom(context, culture, value);
            } 

            ///  
            ///    Converts the given value object to 
            ///       the specified destination type using the specified context and arguments.
            ///  
            public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) {
                return GetConverter(context).ConvertTo(context, culture, value, destinationType);
            }
 
            /// 
            /// Re-creates an  given a set of property values for the 
            ///    object. 
            /// 
            public override object CreateInstance(ITypeDescriptorContext context, IDictionary propertyValues) { 
                return GetConverter(context).CreateInstance(context, propertyValues);
            }

            ///  
            ///     Returns the type converter for the member attributes enum.  We search the context
            ///     for a code dom provider that can provide us more information. 
            ///  
            private TypeConverter GetConverter(ITypeDescriptorContext context) {
                TypeConverter modifierConverter = null; 

                if (context != null) {
                    CodeDomProvider provider = (CodeDomProvider)context.GetService(typeof(CodeDomProvider));
 
                    if (provider != null) {
                        modifierConverter = provider.GetConverter(typeof(MemberAttributes)); 
                    } 
                }
 
                if (modifierConverter == null) {
                    modifierConverter = TypeDescriptor.GetConverter(typeof(MemberAttributes));
                }
 
                return modifierConverter;
            } 
 
            /// 
            ///    Gets a value indicating whether changing a value on this object requires a 
            ///       call to  to create a new value,
            ///       using the specified context.
            /// 
            public override bool GetCreateInstanceSupported(ITypeDescriptorContext context) { 
                return GetConverter(context).GetCreateInstanceSupported(context);
            } 
 
            /// 
            ///    Gets a collection of properties for 
            ///       the type of array specified by the value parameter using the specified context and
            ///       attributes.
            /// 
            public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes) { 
                return GetConverter(context).GetProperties(context, value, attributes);
            } 
 
            /// 
            ///    Gets a value indicating 
            ///       whether this object supports properties using the
            ///       specified context.
            /// 
            public override bool GetPropertiesSupported(ITypeDescriptorContext context) { 
                return GetConverter(context).GetPropertiesSupported(context);
            } 
 
            /// 
            ///    Gets a collection of standard values for the data type this type converter is 
            ///       designed for.
            /// 
            public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context) {
                // We restrict the set of standard values to those within the access mask. 
                //
                StandardValuesCollection values = GetConverter(context).GetStandardValues(context); 
 
                if (values != null && values.Count > 0) {
                    bool needMassage = false; 

                    foreach (MemberAttributes value in values) {
                        if ((value & MemberAttributes.AccessMask) == 0) {
                            needMassage = true; 
                            break;
                        } 
                    } 

                    if (needMassage) { 
                        ArrayList list = new ArrayList(values.Count);

                        foreach (MemberAttributes value in values) {
                            if ((value & MemberAttributes.AccessMask) != 0 && value != MemberAttributes.AccessMask) { 
                                list.Add(value);
                            } 
                        } 

                        values = new StandardValuesCollection(list); 
                    }
                }

                return values; 
            }
 
            ///  
            ///    Gets a value indicating whether the collection of standard values returned from
            ///     is an exclusive 
            ///       list of possible values, using the specified context.
            /// 
            public override bool GetStandardValuesExclusive(ITypeDescriptorContext context) {
                return GetConverter(context).GetStandardValuesExclusive(context); 
            }
 
            ///  
            ///    Gets a value indicating
            ///       whether this object 
            ///       supports a standard set of values that can be picked
            ///       from a list using the specified context.
            /// 
            public override bool GetStandardValuesSupported(ITypeDescriptorContext context) { 
                return GetConverter(context).GetStandardValuesSupported(context);
            } 
 
            /// 
            ///    Gets 
            ///       a value indicating whether the given value object is valid for this type.
            /// 
            public override bool IsValid(ITypeDescriptorContext context, object value) {
                return GetConverter(context).IsValid(context, value); 
            }
        } 
    } 
}
 


// 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