关于IContainer 接口在如下MSDN中解释的应用解析
//This code segment implements the IContainer interface. The code segment
//containing the implementation of ISite and IComponent can be found in the documentation
//for those interfaces.
//Implement the LibraryContainer using the IContainer interface.
class LibraryContainer : IContainer
{
private ArrayList m_bookList;
public LibraryContainer()
{
m_bookList = new ArrayList();
}
public virtual void Add(IComponent book)
{
//The book will be added without creation of the ISite object.
m_bookList.Add(book);
}
public virtual void Add(IComponent book, string ISNDNNum)
{
for(int i =0; i < m_bookList.Count; ++i)
{
IComponent curObj = (IComponent)m_bookList[i];
if(curObj.Site != null)
{
if(curObj.Site.Name.Equals(ISNDNNum))
throw new ArgumentException("The ISBN number already exists in the container");
}
}
ISBNSite data = new ISBNSite(this, book);
data.Name = ISNDNNum;
book.Site = data;
m_bookList.Add(book);
}
public virtual void Remove(IComponent book)
{
for(int i =0; i < m_bookList.Count; ++i)
{
if(book.Equals(m_bookList[i]))
{
m_bookList.RemoveAt(i);
break;
}
}
}
public ComponentCollection Components
{
get
{
IComponent[] datalist = new BookComponent[m_bookList.Count];
m_bookList.CopyTo(datalist);
return new ComponentCollection(datalist);
}
}
public virtual void Dispose()
{
for(int i =0; i < m_bookList.Count; ++i)
{
IComponent curObj = (IComponent)m_bookList[i];
curObj.Dispose();
}
m_bookList.Clear();
}
static void Main(string[] args)
{
LibraryContainer cntrExmpl = new LibraryContainer();
try
{
BookComponent book1 = new BookComponent("Wizard's First Rule", "Terry Gooodkind");
cntrExmpl.Add(book1, "0812548051");
BookComponent book2 = new BookComponent("Stone of Tears", "Terry Gooodkind");
cntrExmpl.Add(book2, "0812548094");
BookComponent book3 = new BookComponent("Blood of the Fold", "Terry Gooodkind");
cntrExmpl.Add(book3, "0812551478");
BookComponent book4 = new BookComponent("The Soul of the Fire", "Terry Gooodkind");
//This will generate exception because the ISBN already exists in the container.
cntrExmpl.Add(book4, "0812551478");
}
catch (ArgumentException e)
{
Console.WriteLine("Unable to add books: " + e.Message);
}
ComponentCollection datalist =cntrExmpl.Components;
IEnumerator denum = datalist.GetEnumerator();
while(denum.MoveNext())
{
BookComponent cmp = (BookComponent)denum.Current;
Console.WriteLine("Book Title: " + cmp.Title);
Console.WriteLine("Book Author: " + cmp.Author);
Console.WriteLine("Book ISBN: " + cmp.Site.Name);
}
}
}
在上面的源码中LibraryContainer充当了容器的角色,BookComponent只包含两个属性,一个是书名Title,一个是作者名Author,但是光凭这两个属性,我们不好唯一标识一本书,因为我们在数据库的概念中,我们一般只会用一个不会重复的字段标识一个元素,在数据库中我们称它为主键。于是这里我们新引入一个类ISBNSite,我们用这个类的Name属性包装书号,同时这个类派生自ISite接口,而BookComponent继承自Component类,通过Component的Site成员,实现了BookComponent与ISBNSite的绑定。
于是我们发现在如上main函数中,我们只要创建一个类似LibraryContainer的容器,并将派生自Component的BookComponent依次添加,就可以通过Components属性返回该BookComponent的集合,并依次访问。
接下来我们拿C#的Button控件类来分析,这个控件类依次派生自ButtonBase->Control->Component类,Component类下有Site属性,是不是觉得有点似曾相识,对,你只要实现一个类似的容器,并添加控件,就可以通过你的容器访问这些控件了,当然也可以通过Dispose统一释放该容器占用的所有控件资源。