The Labs \ Source Viewer \ SSCLI \ System.ComponentModel \ Site

  1. //------------------------------------------------------------------------------
  2. // <copyright file="Container.cs" company="Microsoft">
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. // </copyright>
  14. //------------------------------------------------------------------------------
  15. namespace System.ComponentModel
  16. {
  17.    
  18.     using System;
  19.     using System.ComponentModel;
  20.     using System.Diagnostics;
  21.     using System.Globalization;
  22.     using System.IO;
  23.     using System.Security.Permissions;
  24.    
  25.     /// <devdoc>
  26.     /// <para>
  27.     /// Encapsulates
  28.     /// zero or more components.
  29.     /// </para>
  30.     /// </devdoc>
  31.     [HostProtection(SharedState = true)]
  32.     public class Container : IContainer
  33.     {
  34.         private ISite[] sites;
  35.         private int siteCount;
  36.         private ComponentCollection components;
  37.         private ContainerFilterService filter;
  38.         private bool checkedFilter;
  39.        
  40.         private object syncObj = new object();
  41.        
  42.         ~Container()
  43.         {
  44.             Dispose(false);
  45.         }
  46.        
  47.         // Adds a component to the container.
  48.         /// <devdoc>
  49.         /// <para>
  50.         /// Adds the specified component to the <see cref='System.ComponentModel.Container'/>
  51.         /// . The component is unnamed.
  52.         /// </para>
  53.         /// </devdoc>
  54.         public virtual void Add(IComponent component)
  55.         {
  56.             Add(component, null);
  57.         }
  58.        
  59.         // Adds a component to the container.
  60.         /// <devdoc>
  61.         /// <para>
  62.         /// Adds the specified component to the <see cref='System.ComponentModel.Container'/> and assigns a name to
  63.         /// it.
  64.         /// </para>
  65.         /// </devdoc>
  66.         public virtual void Add(IComponent component, string name)
  67.         {
  68.             lock (syncObj) {
  69.                 if (component == null) {
  70.                     return;
  71.                 }
  72.                
  73.                 ISite site = component.Site;
  74.                
  75.                 if (site != null && site.Container == this) {
  76.                     return;
  77.                 }
  78.                
  79.                 if (sites == null) {
  80.                     sites = new ISite[4];
  81.                 }
  82.                 else {
  83.                     // Validate that new components
  84.                     // have either a null name or a unique one.
  85.                     //
  86.                     ValidateName(component, name);
  87.                    
  88.                     if (sites.Length == siteCount) {
  89.                         ISite[] newSites = new ISite[siteCount * 2];
  90.                         Array.Copy(sites, 0, newSites, 0, siteCount);
  91.                         sites = newSites;
  92.                     }
  93.                 }
  94.                
  95.                 if (site != null) {
  96.                     site.Container.Remove(component);
  97.                 }
  98.                
  99.                 ISite newSite = CreateSite(component, name);
  100.                 sites[siteCount++] = newSite;
  101.                 component.Site = newSite;
  102.                 components = null;
  103.             }
  104.         }
  105.        
  106.         // Creates a site for the component within the container.
  107.         /// <devdoc>
  108.         /// <para>Creates a Site <see cref='System.ComponentModel.ISite'/> for the given <see cref='System.ComponentModel.IComponent'/>
  109.         /// and assigns the given name to the site.</para>
  110.         /// </devdoc>
  111.         protected virtual ISite CreateSite(IComponent component, string name)
  112.         {
  113.             return new Site(component, this, name);
  114.         }
  115.        
  116.         // Disposes of the container. A call to the Dispose method indicates that
  117.         // the user of the container has no further need for it.
  118.         //
  119.         // The implementation of Dispose must:
  120.         //
  121.         // (1) Remove any references the container is holding to other components.
  122.         // This is typically accomplished by assigning null to any fields that
  123.         // contain references to other components.
  124.         //
  125.         // (2) Release any system resources that are associated with the container,
  126.         // such as file handles, window handles, or database connections.
  127.         //
  128.         // (3) Dispose of child components by calling the Dispose method of each.
  129.         //
  130.         // Ideally, a call to Dispose will revert a container to the state it was
  131.         // in immediately after it was created. However, this is not a requirement.
  132.         // Following a call to its Dispose method, a container is permitted to raise
  133.         // exceptions for operations that cannot meaningfully be performed.
  134.         //
  135.         /// <devdoc>
  136.         /// <para>
  137.         /// Disposes of the <see cref='System.ComponentModel.Container'/>
  138.         /// .
  139.         /// </para>
  140.         /// </devdoc>
  141.         public void Dispose()
  142.         {
  143.             Dispose(true);
  144.             GC.SuppressFinalize(this);
  145.         }
  146.        
  147.         protected virtual void Dispose(bool disposing)
  148.         {
  149.             if (disposing) {
  150.                 lock (syncObj) {
  151.                     while (siteCount > 0) {
  152.                         ISite site = sites[--siteCount];
  153.                         site.Component.Site = null;
  154.                         site.Component.Dispose();
  155.                     }
  156.                     sites = null;
  157.                     components = null;
  158.                 }
  159.             }
  160.         }
  161.        
  162.         /// <devdoc>
  163.         /// <para>[To be supplied.]</para>
  164.         /// </devdoc>
  165.         protected virtual object GetService(Type service)
  166.         {
  167.             return ((service == typeof(IContainer)) ? this : null);
  168.         }
  169.        
  170.         // The components in the container.
  171.         /// <devdoc>
  172.         /// <para>
  173.         /// Gets all the components in the <see cref='System.ComponentModel.Container'/>
  174.         /// .
  175.         /// </para>
  176.         /// </devdoc>
  177.         public virtual ComponentCollection Components {
  178.             get {
  179.                 lock (syncObj) {
  180.                     if (components == null) {
  181.                         IComponent[] result = new IComponent[siteCount];
  182.                         for (int i = 0; i < siteCount; i++) {
  183.                             result[i] = sites[i].Component;
  184.                         }
  185.                         components = new ComponentCollection(result);
  186.                        
  187.                         // At each component add, if we don't yet have a filter, look for one.
  188.                         // Components may add filters.
  189.                         if (filter == null && checkedFilter) {
  190.                             checkedFilter = false;
  191.                         }
  192.                     }
  193.                    
  194.                     if (!checkedFilter) {
  195.                         filter = GetService(typeof(ContainerFilterService)) as ContainerFilterService;
  196.                         checkedFilter = true;
  197.                     }
  198.                    
  199.                     if (filter != null) {
  200.                         ComponentCollection filteredComponents = filter.FilterComponents(components);
  201.                         Debug.Assert(filteredComponents != null, "Incorrect ContainerFilterService implementation.");
  202.                         if (filteredComponents != null) {
  203.                             components = filteredComponents;
  204.                         }
  205.                     }
  206.                    
  207.                     return components;
  208.                 }
  209.             }
  210.         }
  211.        
  212.         // Removes a component from the container.
  213.         /// <devdoc>
  214.         /// <para>
  215.         /// Removes a component from the <see cref='System.ComponentModel.Container'/>
  216.         /// .
  217.         /// </para>
  218.         /// </devdoc>
  219.         public virtual void Remove(IComponent component)
  220.         {
  221.             Remove(component, false);
  222.         }
  223.        
  224.         private void Remove(IComponent component, bool preserveSite)
  225.         {
  226.             lock (syncObj) {
  227.                 if (component == null)
  228.                     return;
  229.                 ISite site = component.Site;
  230.                 if (site == null || site.Container != this)
  231.                     return;
  232.                 if (!preserveSite)
  233.                     component.Site = null;
  234.                 for (int i = 0; i < siteCount; i++) {
  235.                     if (sites[i] == site) {
  236.                         siteCount--;
  237.                         Array.Copy(sites, i + 1, sites, i, siteCount - i);
  238.                         sites[siteCount] = null;
  239.                         components = null;
  240.                         break;
  241.                     }
  242.                 }
  243.             }
  244.         }
  245.        
  246.         protected void RemoveWithoutUnsiting(IComponent component)
  247.         {
  248.             Remove(component, true);
  249.         }
  250.        
  251.         /// <devdoc>
  252.         /// Validates that the given name is valid for a component. The default implementation
  253.         /// verifies that name is either null or unique compared to the names of other
  254.         /// components in the container.
  255.         /// </devdoc>
  256.         protected virtual void ValidateName(IComponent component, string name)
  257.         {
  258.            
  259.             if (component == null) {
  260.                 throw new ArgumentNullException("component");
  261.             }
  262.            
  263.             if (name != null) {
  264.                 for (int i = 0; i < Math.Min(siteCount, sites.Length); i++) {
  265.                     ISite s = sites[i];
  266.                    
  267.                     if (s != null && s.Name != null && string.Equals(s.Name, name, StringComparison.OrdinalIgnoreCase) && s.Component != component) {
  268.                         InheritanceAttribute inheritanceAttribute = (InheritanceAttribute)TypeDescriptor.GetAttributes(s.Component)[typeof(InheritanceAttribute)];
  269.                         if (inheritanceAttribute.InheritanceLevel != InheritanceLevel.InheritedReadOnly) {
  270.                             throw new ArgumentException(SR.GetString(SR.DuplicateComponentName, name));
  271.                         }
  272.                     }
  273.                 }
  274.             }
  275.         }
  276.        
  277.         private class Site : ISite
  278.         {
  279.             private IComponent component;
  280.             private Container container;
  281.             private string name;
  282.            
  283.             internal Site(IComponent component, Container container, string name)
  284.             {
  285.                 this.component = component;
  286.                 this.container = container;
  287.                 this.name = name;
  288.             }
  289.            
  290.             // The component sited by this component site.
  291.             public IComponent Component {
  292.                 get { return component; }
  293.             }
  294.            
  295.             // The container in which the component is sited.
  296.             public IContainer Container {
  297.                 get { return container; }
  298.             }
  299.            
  300.             public object GetService(Type service)
  301.             {
  302.                 return ((service == typeof(ISite)) ? this : container.GetService(service));
  303.             }
  304.            
  305.            
  306.             // Indicates whether the component is in design mode.
  307.             public bool DesignMode {
  308.                 get { return false; }
  309.             }
  310.            
  311.             // The name of the component.
  312.             //
  313.             public string Name {
  314.                 get { return name; }
  315.                 set {
  316.                     if (value == null || name == null || !value.Equals(name)) {
  317.                         container.ValidateName(component, value);
  318.                         name = value;
  319.                     }
  320.                 }
  321.             }
  322.         }
  323.     }
  324. }

Developer Fusion