• 反编译 Component重要类,全文解释 - 容器篇


    using System;
    using System.Security.Permissions;

    namespace System.ComponentModel {

        
    /// <summary>
        
    /// 容器类
        
    /// </summary>

        [HostProtection(SecurityAction.LinkDemand, SharedState = true)]
        
    public class Container : IContainer, IDisposable {
            
    /// <summary>
            
    /// 初始化对象
            
    /// </summary>

            public Container() {
                
    //用于锁定的锁定资源
                this.syncObj = new object();
            }


            
    /// <summary>
            
    /// 向容器添加新的组件
            
    /// </summary>
            
    /// <param name="component">新加入的组件</param>

            public virtual void Add(IComponent component) {
                
    //Name为null处理
                this.Add(component, null);
            }


            
    /// <summary>
            
    /// 向容器添加新的组件并指定名称
            
    /// </summary>
            
    /// <param name="component">新添加的组件</param>
            
    /// <param name="name">组件的名称</param>

            public virtual void Add(IComponent component, string name) {
                
    //防止并发添加
                lock (this.syncObj) {
                    
    //允许component参数为null,并不出错,而是忽略
                    if (component == null{
                        
    return;
                    }


                    ISite oldSite 
    = component.Site;
                    
    //如果新加入的组件包含了站点对象,且站点指向的就是自己,就不继续添加了;
                    
    //说白了,就是不允许重复加入容器
                    if ((oldSite != null&& (oldSite.Container == this)) {
                        
    return;
                    }


                    
    //如果没有初始化过站点数组,就初始化4个
                    if (this.sites == null{
                        
    this.sites = new ISite[4];
                    }

                    
    else {
                        
    //??难度第一次就用校验名称了吗?
                        this.ValidateName(component, name);

                        
    //站点对象是存放在数组中的,所以当空间不足时,需要手工增大。
                        if (this.sites.Length == this.siteCount) {
                            
    //新的大小是原大小的2倍。
                            ISite[] newSites = new ISite[this.siteCount * 2];
                            
    //将原始数据复制到新的数组
                            Array.Copy(this.sites, 0, newSites, 0this.siteCount);
                            
    this.sites = newSites;
                        }

                    }


                    
    //如果新加入的组件,原先有一个容器了,就应该从原容器中移除。不能有俩个老爸吧。
                    if (oldSite != null{
                        oldSite.Container.Remove(component);
                    }


                    
    //创建新的站点对象,这个CreateSite是可以重载的。
                    ISite newSite = this.CreateSite(component, name);
                    
    //增加站点计数器,并将新站点放在容器的最后。
                    this.sites[this.siteCount++= newSite;
                    
    //为组件注射新的站点对象。
                    component.Site = newSite;
                    
    //注意这里:他将components设置为null,以便Components属性重构数组的内容,
                    
    //当现在就没有必要马上重构,优化
                    this.components = null;
                }

            }


            
    /// <summary>
            
    /// 为新组件创建站点对象
            
    /// </summary>
            
    /// <param name="component">要创建站点的组件对象</param>
            
    /// <param name="name">组件预定的名称</param>
            
    /// <returns>新的站点对象</returns>

            protected virtual ISite CreateSite(IComponent component, string name) {
                
    return new Container.Site(component, this, name);
            }


            
    /// <summary>
            
    /// 释放当前容器对象
            
    /// </summary>

            public void Dispose() {
                
    //这个方法是不能重载的,但是他会调用下面的方法,而这个方法是可重载的。
                this.Dispose(true);
                
    //回收我吧。
                GC.SuppressFinalize(this);
            }


            
    /// <summary>
            
    /// 重载此方法来释放自定义的资源
            
    /// </summary>
            
    /// <param name="disposing">true表示调用方主动提出释放,false表示是垃圾回收器在调用此方法。</param>

            protected virtual void Dispose(bool disposing) {
                
    //只有主动要求释放的时候才会做这些事情。
                if (disposing) {
                    
    //锁定一下,并发小心啊。
                    lock (this.syncObj) {
                        
    int i;
                        
    //循环所有的子组件,将他们一一释放,也就是说,
                        
    //我不能活,我的孩子们也要死。好残忍哦。
                        while (this.siteCount > 0{
                            
    //怎么喜欢联等号,看着不舒服,这个释放过程是从后向前释放的。
                            this.siteCount = i = this.siteCount - 1;
                            ISite site 
    = this.sites[i];
                            
    //取消组件的站点引用,然后释放他。
                            site.Component.Site = null;
                            site.Component.Dispose();
                        }

                        
    //取消所有站点的引用,也就是取消了对所有子组件的引用。
                        
    //虽然站点持有了容器的引用,但是现在容器不持有站点了,
                        
    //也就取消了循环引用。
                        this.sites = null;
                        
    this.components = null;
                    }

                }

            }


            
    /// <summary>
            
    /// 当容器被垃圾回收器回收前调用
            
    /// </summary>

            ~Container() {
                
    //一般的,这个调用基本上没有什么事情可做。
                this.Dispose(false);
            }


            
    /// <summary>
            
    /// 获取服务
            
    /// </summary>
            
    /// <param name="service">要获取的服务类型</param>
            
    /// <returns>如果找到此服务就返回服务的实例,否则返回null</returns>

            protected virtual object GetService(Type service) {
                
    //在默认的Component实现中,他的GetService最终就是调用这个容器的GetService
                
    //所以,要为组件提供其他的服务,可以重载此方法已提供更多的服务
                if (service != typeof(IContainer)) {
                    
    return null;
                }

                
    return this;
            }


            
    /// <summary>
            
    /// 从容器中移除指定的组件
            
    /// </summary>
            
    /// <param name="component">要移除的组件对象</param>

            public virtual void Remove(IComponent component) {
                
    this.Remove(component, false);
            }


            
    //这个是实际的移除方法
            private void Remove(IComponent component, bool preserveSite) {
                
    //还是小心并发
                lock (this.syncObj) {
                    
    //允许参数为null,不出错,退出。
                    if (component == null{
                        
    return;
                    }


                    
    //获取要移除的组件站点对象
                    ISite oldSite = component.Site;
                    
    //没有站点对象,不关我的事情,退出
                    if (oldSite == null{
                        
    return;
                    }

                    
    //不是我容器下的东西,也不关我的事情,退出
                    if (oldSite.Container != this{
                        
    return;
                    }


                    
    //首先组件的站点对象,不再指向他。
                    if (!preserveSite) {
                        component.Site 
    = null;
                    }


                    
    //找到他,移除的时候比较简单,并不调用他的Dispose方法,奇怪。
                    for (int i = 0; i < this.siteCount; i++{
                        
    if (this.sites[i] == oldSite) {
                            
    //减少计数器
                            this.siteCount--;
                            
    //将删除的位置之后的数据向前移动一个。
                            Array.Copy(this.sites, (int)(i + 1), this.sites, i, (int)(this.siteCount - i));
                            
    //将最后一个站点设置为空
                            this.sites[this.siteCount] = null;
                            
    //内容发生变化,设置components为null,以便重新构建
                            this.components = null;
                            
    return;
                        }

                    }

                }

            }


            
    /// <summary>
            
    /// 移除组件,但不删除组件的站点属性。
            
    /// </summary>
            
    /// <param name="component">要移除的组件</param>

            protected void RemoveWithoutUnsiting(IComponent component) {
                
    //这是一个特殊的方法,不知用在什么地方。
                this.Remove(component, true);
            }


            
    /// <summary>
            
    /// 校验新加入的组件的名称正确性
            
    /// </summary>
            
    /// <param name="component">要校验的组件</param>
            
    /// <param name="name">组件的名称</param>

            protected virtual void ValidateName(IComponent component, string name) {
                
    //参数校验
                if (component == null{
                    
    throw new ArgumentNullException("component");
                }


                
    //没有名字,不算有问题
                if (name != null{
                    
    //循环所有的站点。但不明白的是为什么要取站点的最小值和数组的最小值,难道siteCount不是总是小于sites.Length的吗?
                    for (int i = 0; i < Math.Min(this.siteCount, this.sites.Length); i++{
                        ISite site 
    = this.sites[i];
                        
    //如果 站点有效 且
                        
    //     站点有名字 且
                        
    //     站点的名字和新名字相等 且
                        
    //     站点对应的组件不是检查的组件(自己)。
                        if (((site != null&& (site.Name != null)) &&                         
                            (
    string.Equals(site.Name, name, StringComparison.OrdinalIgnoreCase) && (site.Component != component))) {
                            
    //该组件会被继承并且是只读的,就不报错,Why?
                            InheritanceAttribute attribute1 = (InheritanceAttribute)TypeDescriptor.GetAttributes(site.Component)[typeof(InheritanceAttribute)];
                            
    if (attribute1.InheritanceLevel != InheritanceLevel.InheritedReadOnly) {
                                
    throw new ArgumentException("名字重复了", name);
                            }

                        }

                    }

                }

            }


            
    /// <summary>
            
    /// 获取容器的所有组件
            
    /// </summary>

            public virtual ComponentCollection Components {
                
    get {
                    
    //组件集合是动态创建的。
                    ComponentCollection retCollection;
                    
    lock (this.syncObj) {
                        
    if (this.components == null{
                            
    //创建一个数组,将所有的站点的组件对象收集起来
                            IComponent[] newComponents = new IComponent[this.siteCount];
                            
    for (int i = 0; i < this.siteCount; i++{
                                newComponents[i] 
    = this.sites[i].Component;
                            }

                            
    //这个赋值好像早了点,因为如果过滤服务失败,下次方法Components时就时错误的结果了,
                            
    //因为comonents已经不是null了。
                            this.components = new ComponentCollection(newComponents);
                            
    //初始化状态checkedFilter为false,所以即使下面的条件不通过,也还是会去申请的。
                            
    //如果申请过了,但是上次没有申请到,就重新申请。
                            
    //只要有一次成功申请到,就不会再申请了。
                            if ((this.filter == null&& this.checkedFilter) {
                                
    this.checkedFilter = false;
                            }

                        }

                        
    //如果没有申请过过滤服务,就申请一次。
                        if (!this.checkedFilter) {
                            
    //缓存过滤服务,总觉得缓存危险
                            this.filter = this.GetService(typeof(ContainerFilterService)) as ContainerFilterService;
                            
    this.checkedFilter = true;
                        }

                        
    //过滤服务有效
                        if (this.filter != null{
                            
    //过滤数据,过滤有结果,才放入新结果
                            ComponentCollection newCollection = this.filter.FilterComponents(this.components);
                            
    if (newCollection != null{
                                
    this.components = newCollection;
                            }

                        }

                        retCollection 
    = this.components;
                    }

                    
    return retCollection;
                }

            }


            
    // Fields
            private bool checkedFilter;                     //申请过过滤服务吗
            private ComponentCollection components;         //缓存的组件集合
            private ContainerFilterService filter;          //缓存的过滤服务
            private int siteCount;                          //当前站点总数
            private ISite[] sites;                          //当前所有的站点存放处(可能有空地)
            private object syncObj;                         //锁定对象

            
    /// <summary>
            
    /// 内置的站点对象,不需要公开的.
            
    /// </summary>

            private class Site : ISite, IServiceProvider {
                
    /// <summary>
                
    /// 初始化站点
                
    /// </summary>
                
    /// <param name="component">站点对应的组件</param>
                
    /// <param name="container">所在容器</param>
                
    /// <param name="name">新的名称</param>

                internal Site(IComponent component, Container container, string name) {
                    
    this.component = component;
                    
    this.container = container;
                    
    this.name = name;
                }


                
    /// <summary>
                
    /// 获取服务
                
    /// </summary>
                
    /// <param name="service">服务类型</param>
                
    /// <returns>服务实例</returns>

                public object GetService(Type service) {
                    
    //如果申请的是ISite,就是自己了.
                    if (service != typeof(ISite)) {
                        
    //实际调用的是容器的GetService
                        
    //Component的GetService调用顺序是:
                        
    // Component.GetService -> Site.GetService -> Container.GetService
                        return this.container.GetService(service);
                    }

                    
    return this;
                }

     

                
    /// <summary>
                
    /// 返回站点关联的组件
                
    /// </summary>

                public IComponent Component {
                    
    get {
                        
    return this.component;
                    }

                }


                
    /// <summary>
                
    /// 返回站点所在的容器
                
    /// </summary>

                public IContainer Container {
                    
    get {
                        
    return this.container;
                    }

                }


                
    /// <summary>
                
    /// 返回是否是设计模式
                
    /// </summary>

                public bool DesignMode {
                    
    get {
                        
    //总是返回false,真的不知道为什么设计成一个属性,而不是GetService(IDesignService)的方式。郁闷
                        return false;
                    }

                }


                
    /// <summary>
                
    /// 返回/设置站点的名称
                
    /// </summary>

                public string Name {
                    
    get {
                        
    return this.name;
                    }

                    
    set {
                        
    //校验名称,名字只会存储在这里。
                        if (((value == null|| (this.name == null)) || !value.Equals(this.name)) {
                            
    this.container.ValidateName(this.component, value);
                            
    this.name = value;
                        }

                    }

                }

     
                
    private IComponent component;
                
    private Container container;
                
    private string name;
            }

        }

    }

  • 相关阅读:
    .NET开发者必备的工具箱
    LINQ标准查询操作符详解(转)
    转)SSO单点登录在互联网电商应用中的解决方案(基于CAS的改造)
    构建高并发高可用的电商平台架构实践(转)
    使用UI Automation实现自动化测试 --微软提供的控件Pattern
    使用UI Automation实现自动化测试 --工具使用
    [archlinux][daily] 自建DNS服务器 / 建立本地DNS cache / 使用dnsmasq加速上网
    [skill] 补码
    nfs的时间问题,影响编译
    [daily][CentOS][SELinux]用key免登陆不成功,原来是SElinux在搞事情
  • 原文地址:https://www.cnblogs.com/tansm/p/303525.html
Copyright © 2020-2023  润新知