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;
}
}
}
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;
}
}
}