随笔- 302
文章- 0
评论- 895
阅读-
78万
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, 0, this.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;
}
}
}

posted on
2005-12-23 17:24
编写人生
阅读(
790)
评论()
编辑
收藏
举报
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构