Castle IOC是Castle的核心和灵魂。有一句话是这么说的,如果要理解castle和spring这样的框架,必须首先理解其IOC。当然,如果停留在使用层次那就不需要了。本章帮你一起揭密Castle IOC本质。
接上篇的问题。先摆一个核心类图
乖乖,那么复杂。一一分析。
IServiceProviderEx:继承自IServiceProvider,扩充了public object GetService(Type serviceType)的范型版本public T GetService<T>().这个可以看做是对.net基本类库的扩充。IWindsorContainer和IKernal均继承此接口
Ikernal: MicroKernal核心接口。Castle的核心容器是microkernal,所有基本和基础实现都在microkernal中.如容器的组件(1:component 2:facility )注入,Hanlder的创建,组件依赖关系的识别(包括配置文件方式),动态加入依赖关系,组件Resolve,组件激活,组件使用代理激活,组件各种激活方式,容器对组件生命周期的管理和各种事件,组件配置的序列化和反序列化等)
IWindsorContainer:核心接口。提供了在容器重查找,注册component的方法。同时提供操作子容器,父容器的方法。有多个重载方法,例如AddComponent,AddFacility,resolve等。
IWindsorContainer:依赖IKernal,可以看做是Ikernal的封装和扩充,四个方面的扩展(见备注)。所以IWindsorContainer具有Ikernal的所有功能IWindsorContainer
实例分析下,引用上篇的例子,首先构造一个windsorContainer,windsorContainer是IWindsorContainer的缺省实现。
1: IWindsorContainer container = new WindsorContainer();
2:
3: [Serializable]
4:
5: public class WindsorContainer : MarshalByRefObject, IWindsorContainer
6:
7: {
8:
9: private readonly string name = Guid.NewGuid().ToString();
10:
11: private readonly IDictionary childContainers = Hashtable.Synchronized(new Hashtable());
12:
13: private IKernel kernel;
14:
15: private IWindsorContainer parent;
16:
17: private IComponentsInstaller installer;
18:
19: }
调用缺省构造造器后,初始化了缺省的DefaultKernel和DefaultComponentInstaller
1: public WindsorContainer() : this(new DefaultKernel(), new Installer.DefaultComponentInstaller())
2:
3: {
4:
5: }
调用到
1: public WindsorContainer(IKernel kernel, IComponentsInstaller installer) : this(Guid.NewGuid().ToString(), kernel, installer)
2:
3: {
4:
5: }
给组件分配了个guid作为名字,这在父子容器中用到。继续调用到
1: public WindsorContainer(String name, IKernel kernel, IComponentsInstaller installer)
2:
3: {
4:
5: this.name = name;
6:
7: this.kernel = kernel;
8:
9: this.kernel.ProxyFactory = new Proxy.DefaultProxyFactory();
10:
11: this.installer = installer;
12:
13: }
这里初始化了default的ProxyFactory(使用到了dynamicProxy)分配给defaultKernal的proxyFactory。在MicroKernal中默认是不使用proxy的(NotSupportedProxyFactory)。
容器初始化完成,其实这里的重点是对MicroKernal的初始化,new DefaultKernel(),这里涉及很多内容,后面分解,先假设默认理解最核心的Kernal已经构建好。
下面加入组件:
container.AddComponent("mailSender", typeof (IEmailSender), typeof (SmtpEmailSender));
AddComponent有很多重载方法,
1:serviceType =classType,
IWindsorContainer AddComponent(String key, Type classType);
2:classType是serviceType的实现类型
IWindsorContainer AddComponent(String key, Type serviceType, Type classType);
3:加入了组件lifestyle,lifestyle概念参见第一篇
IWindsorContainer AddComponentLifeStyle(String key, Type classType, LifestyleType lifestyle);
IWindsorContainer AddComponentLifeStyle(String key, Type serviceType, Type classType, LifestyleType lifestyle);
4:加入了一些扩展属性。用处后面解释
IWindsorContainer AddComponentWithProperties(String key, Type classType, IDictionary extendedProperties);
IWindsorContainer AddComponentWithProperties(String key, Type serviceType, Type classType, IDictionary extendedProperties);
5:范型版本,此处key =typeof(T)
IWindsorContainer AddComponent<T>();
IWindsorContainer AddComponent<T>(String key);
略。。。
无论哪种方法,最终都是交给Kernal去处理。例如
public IWindsorContainer AddComponentLifeStyle(string key, Type serviceType, Type classType, LifestyleType lifestyle)
{
kernel.AddComponent(key, serviceType, classType, lifestyle, true);
return this;
}
public IWindsorContainer AddComponentLifeStyle(string key, Type serviceType, Type classType, LifestyleType lifestyle)
{
kernel.AddComponent(key, serviceType, classType, lifestyle, true);
return this;
}
对于AddFacility,原理一样。任何实现了IFacility接口的组件都可以被加入到容器中(castle就是依靠这个整合扩充了很多优秀的其他第三方组件啊,比如Ibastis,Log4,nHibernate,WCF…,呵呵)。下列是几个重载方法,可以加入一个缺省type =T的facility。
IWindsorContainer AddFacility(String key, IFacility facility);
IWindsorContainer AddFacility<T>(String key) where T : IFacility, new();
IWindsorContainer AddFacility<T>() where T : IFacility, new();
获取组件:
INewsletterService newsLetterService = container["newLetter"] as INewsletterService ;
调用了对象Index
很明显,一个根据key来获取,一个根据serviceType来获取。所以不可能加入多于一个的相同key和type的组件。对象Index调用到Resovle方法。同样,Resolve有很多重载版本,就不一一列举了。举一个例子,
public virtual object Resolve(String key, Type service, IDictionary arguments)
{
return kernel.Resolve(key, service, arguments);
}
这里也是最终转调的Ikernal的Resolve方法。
好了,今天写到此,相信大家比以前更加了解了些。呵呵
待续。。。。。。。
注: castle的核心容器实现是MicroKernal 组件,WindsorContainer在其上做了下列方面的扩充
public void SetUp(IWindsorContainer container, IConfigurationStore store)
{
SetUpComponents(store.GetBootstrapComponents(), container);
SetUpFacilities(store.GetFacilities(), container);
SetUpComponents(store.GetComponents(), container);
SetUpChildContainers(store.GetConfigurationForChildContainers(), container);
}