ReferenceService.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ DotNET / DotNET / 8.0 / untmp / whidbey / REDBITS / ndp / fx / src / Designer / Host / ReferenceService.cs / 1 / ReferenceService.cs

                            //------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 
namespace System.ComponentModel.Design {
 
    using System; 
    using System.Collections;
    using System.ComponentModel; 
    using System.ComponentModel.Design;
    using System.Diagnostics;
    using System.Globalization;
 
    /// 
    ///     This service allows clients to work with all references on a form, not just 
    ///     the top-level sited components. 
    /// 
    internal sealed class ReferenceService : IReferenceService, IDisposable { 

        private static readonly Attribute[] _attributes = new Attribute[] {DesignerSerializationVisibilityAttribute.Content};

        private IServiceProvider  _provider;            // service provider we use to get to other services 
        private ArrayList         _addedComponents;     // list of newly added components
        private ArrayList         _removedComponents;   // list of newly removed components 
        private ArrayList         _references;          // our current list of references 
        private bool              _populating;
 
        /// 
        ///     Constructs the ReferenceService.
        /// 
        internal ReferenceService(IServiceProvider provider) { 
            _provider = provider;
        } 
 
        /// 
        ///     Creates an entry for a top-level component and it's children. 
        /// 
        private void CreateReferences(IComponent component) {
            CreateReferences(string.Empty, component, component);
        } 

        ///  
        ///     Recursively creates references for namespaced objects. 
        /// 
        private void CreateReferences(string trailingName, object reference, IComponent sitedComponent) { 

            if (object.ReferenceEquals(reference, null)) {
                return;
            } 

            _references.Add(new ReferenceHolder(trailingName, reference, sitedComponent)); 
 
            foreach(PropertyDescriptor property in TypeDescriptor.GetProperties(reference, _attributes)) {
                if (property.IsReadOnly) { 
                    CreateReferences(
                        string.Format(CultureInfo.CurrentCulture, "{0}.{1}", trailingName, property.Name),
                        property.GetValue(reference),
                        sitedComponent); 
                }
            } 
        } 

        ///  
        ///     Demand populates the _references variable.
        /// 
        private void EnsureReferences() {
 
            // If the references are null, create them for the first time and connect
            // up our events to listen to changes to the container.  Otherwise, check to 
            // see if the added or removed lists contain anything for us to sync up. 
            //
            if (_references == null) { 

                if (_provider == null) {
                    throw new ObjectDisposedException("IReferenceService");
                } 

                IComponentChangeService cs = _provider.GetService(typeof(IComponentChangeService)) as IComponentChangeService; 
                Debug.Assert(cs != null, "Reference service relies on IComponentChangeService"); 
                if (cs != null) {
                    cs.ComponentAdded += new ComponentEventHandler(this.OnComponentAdded); 
                    cs.ComponentRemoved += new ComponentEventHandler(this.OnComponentRemoved);
                    cs.ComponentRename += new ComponentRenameEventHandler(this.OnComponentRename);
                }
 
                IContainer container = _provider.GetService(typeof(IContainer)) as IContainer;
                if (container == null) { 
                    Debug.Fail("Reference service cannot operate without IContainer"); 
                    throw new InvalidOperationException();
                } 

                _references = new ArrayList(container.Components.Count);

                foreach(IComponent component in container.Components) { 
                    CreateReferences(component);
                } 
            } 
            else  if (!_populating) {
                _populating = true; 
                try {
                    if (_addedComponents != null && _addedComponents.Count > 0) {

                        // There is a possibility that this component already exists. 
                        // If it does, just remove it first and then re-add it.
                        // 
                        foreach (IComponent ic in _addedComponents) { 
                            RemoveReferences(ic);
                            CreateReferences(ic); 
                        }

                        _addedComponents.Clear();
                    } 

                    if (_removedComponents != null && _removedComponents.Count > 0) { 
                        foreach (IComponent ic in _removedComponents) { 
                            RemoveReferences(ic);
                        } 

                        _removedComponents.Clear();
                    }
                } 
                finally {
                    _populating = false; 
                } 
            }
        } 

        /// 
        ///     Listens for component additions to find all the references it contributes.
        ///  
        private void OnComponentAdded(object sender, ComponentEventArgs cevent) {
 
            if (_addedComponents == null) { 
                _addedComponents = new ArrayList();
            } 

            IComponent compAdded = cevent.Component;
            if (!(compAdded.Site is INestedSite))
            { 
                _addedComponents.Add(compAdded);
 
                if (_removedComponents != null) { 
                    _removedComponents.Remove(compAdded);
                } 
            }
        }

        ///  
        ///     Listens for component removes to delete all the references it holds.
        ///  
        private void OnComponentRemoved(object sender, ComponentEventArgs cevent) { 

            if (_removedComponents == null) { 
                _removedComponents = new ArrayList();
            }

            IComponent compRemoved = cevent.Component; 
            if (!(compRemoved.Site is INestedSite))
            { 
                _removedComponents.Add(compRemoved); 

                if (_addedComponents != null) { 
                    _addedComponents.Remove(compRemoved);
                }
            }
        } 

        ///  
        ///     Listens for component removes to delete all the references it holds. 
        /// 
        private void OnComponentRename(object sender, ComponentRenameEventArgs cevent) { 
            foreach (ReferenceHolder reference in _references) {
                if (object.ReferenceEquals(reference.SitedComponent, cevent.Component)) {
                    reference.ResetName();
                    return; 
                }
            } 
        } 

        ///  
        ///     Removes all the references that this component owns.
        /// 
        private void RemoveReferences(IComponent component) {
            if (_references != null) { 
                int size = _references.Count;
                for (int i = size - 1; i >= 0; i--) { 
                    if (object.ReferenceEquals(((ReferenceHolder)_references[i]).SitedComponent, component)) { 
                        _references.RemoveAt(i);
                    } 
                }
            }
        }
 
        /// 
        ///     Cleanup and detach from our events. 
        ///  
        void IDisposable.Dispose() {
 
            if (_references != null && _provider != null) {

                IComponentChangeService cs = _provider.GetService(typeof(IComponentChangeService)) as IComponentChangeService;
                if (cs != null) { 
                    cs.ComponentAdded -= new ComponentEventHandler(this.OnComponentAdded);
                    cs.ComponentRemoved -= new ComponentEventHandler(this.OnComponentRemoved); 
                    cs.ComponentRename -= new ComponentRenameEventHandler(this.OnComponentRename); 
                }
 
                _references = null;
                _provider = null;
            }
        } 

        ///  
        ///     Finds the sited component for a given reference, returning null if not found. 
        /// 
        IComponent IReferenceService.GetComponent(object reference) { 

            if (object.ReferenceEquals(reference, null)) {
                throw new ArgumentNullException("reference");
            } 

            EnsureReferences(); 
 
            foreach(ReferenceHolder holder in _references) {
                if (object.ReferenceEquals(holder.Reference, reference)) { 
                    return holder.SitedComponent;
                }
            }
 
            return null;
        } 
 
        /// 
        ///     Finds name for a given reference, returning null if not found. 
        /// 
        string IReferenceService.GetName(object reference) {

            if (object.ReferenceEquals(reference, null)) { 
                throw new ArgumentNullException("reference");
            } 
 
            EnsureReferences();
 
            foreach(ReferenceHolder holder in _references) {
                if (object.ReferenceEquals(holder.Reference, reference)) {
                    return holder.Name;
                } 
            }
 
            return null; 
        }
 
        /// 
        ///     Finds a reference with the given name, returning null if not found.
        /// 
        object IReferenceService.GetReference(string name) { 

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

            foreach(ReferenceHolder holder in _references) {
                if (string.Equals(holder.Name, name, StringComparison.OrdinalIgnoreCase)) { 
                    return holder.Reference;
                } 
            } 

            return null; 
        }

        /// 
        ///     Returns all references available in this designer. 
        /// 
        object[] IReferenceService.GetReferences() { 
            EnsureReferences(); 

            object[] references = new object[_references.Count]; 

            for(int i = 0; i < references.Length; i++) {
                references[i] = ((ReferenceHolder)_references[i]).Reference;
            } 

            return references; 
        } 

        ///  
        ///     Returns all references available in this designer that are assignable to the given type.
        /// 
        object[] IReferenceService.GetReferences(Type baseType) {
 
            if (baseType == null) {
                throw new ArgumentNullException("baseType"); 
            } 

            EnsureReferences(); 

            ArrayList results = new ArrayList(_references.Count);

            foreach(ReferenceHolder holder in _references) { 
                object reference = holder.Reference;
                if (baseType.IsAssignableFrom(reference.GetType())) { 
                    results.Add(reference); 
                }
            } 

            object[] references = new object[results.Count];
            results.CopyTo(references, 0);
            return references; 
        }
 
        ///  
        ///     The class that holds the information about a reference.
        ///  
        private sealed class ReferenceHolder {

            private string      _trailingName;
            private object      _reference; 
            private IComponent  _sitedComponent;
            private string      _fullName; 
 
            /// 
            ///     Creates a new reference holder. 
            /// 
            internal ReferenceHolder(string trailingName, object reference, IComponent sitedComponent) {

                _trailingName = trailingName; 
                _reference = reference;
                _sitedComponent = sitedComponent; 
 
                Debug.Assert(trailingName != null, "Expected a trailing name");
                Debug.Assert(reference != null, "Expected a reference"); 

                #if DEBUG
                Debug.Assert(sitedComponent != null, "Expected a sited component");
                if (sitedComponent != null) Debug.Assert(sitedComponent.Site != null, "Sited component is not really sited: " + sitedComponent.ToString()); 
                if (sitedComponent != null) Debug.Assert(TypeDescriptor.GetComponentName(sitedComponent) != null, "Sited component has no name: " + sitedComponent.ToString());
                #endif // DEBUG 
            } 

            ///  
            ///     Resets the name of this reference holder.  It will be re-aquired on demand
            /// 
            internal void ResetName() {
                _fullName = null; 
            }
 
            ///  
            ///     The name of the reference we are holding.
            ///  
            internal string Name {
                get {
                    if (_fullName == null) {
                        if (_sitedComponent != null) { 
                            string siteName = TypeDescriptor.GetComponentName(_sitedComponent);
                            if (siteName != null) { 
                                _fullName = string.Format(CultureInfo.CurrentCulture, "{0}{1}", siteName, _trailingName); 
                            }
                        } 

                        if (_fullName == null) {
                            _fullName = string.Empty;
                            #if DEBUG 
                            if (_sitedComponent != null) Debug.Assert(_sitedComponent.Site != null, "Sited component is not really sited: " + _sitedComponent.ToString());
                            if (_sitedComponent != null) Debug.Assert(TypeDescriptor.GetComponentName(_sitedComponent) != null, "Sited component has no name: " + _sitedComponent.ToString()); 
                            #endif // DEBUG 
                        }
                    } 
                    return _fullName;
                }
            }
 
            /// 
            ///     The reference we are holding. 
            ///  
            internal object Reference {
                get { 
                    return _reference;
                }
            }
 
            /// 
            ///     The sited component associated with this reference. 
            ///  
            internal IComponent SitedComponent {
                get { 
                    return _sitedComponent;
                }
            }
        } 
    }
} 
 

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