这一节我们来分析Facility,作为Castle的可扩展单元,他是可以带有注入性的,也就是对组件来说,他可能“侵犯”组件本身。下面我们从官方提供的一个Startable的Facility开始。
先明白这个Facility的作用,也就是要达到的目的:使一个实现了Castle.Model.IStartable接口的程序在满足依赖性的时候,能够自我执行。
{
void Start(); // 创建的时候执行
void Stop(); // 销毁的时候执行
}
首先我们来了解一下这个接口:ILifecycleConcern,这个接口带有一个方法:
{
void Apply( ComponentModel model, object component );
}
他用来在组件特定的生命周期提供处理行为。
比如,我们上一节提到的,实现了IInitializable接口的组件,容器会自动调用组件的初始化方法Initialize,只是执行这个接口的Facility是内置的(Kernel自带)。
接着,我们来用两个类实现这个接口:
第一个StartConcern,处理:如果是实现IStartable的组件则调用其Start()方法:
{
(component as IStartable).Start();
}
第二个StopConcern,处理:如果实现IStartable的组件则调用其Stop()方法:
{
(component as IStartable).Stop();
}
先别问为什么,知道功能就好,下面会继续讲到。
好了,我们看下如何实现一个Facility,创建一个自定的Facility可以直接实现IFacility接口,或者从AbstractFacility中继承下来,他们的不同支出只是AbstractFacility提供了IFacility接口的默认实现,你只需实现Init()方法即可。但其实IFacility包含的东西并不多,只有两个:
{
// Facility被添加到容器中就立刻执行
void Init(IKernel kernel, IConfiguration facilityConfig);
// 一般在容器的Dispose()中被调用
void Terminate();
}
既然我们要达到程序的自启动,好自然,我们应该在组件加入容器的时候检查其依赖性满足后就启动他。那么如何让自定的Facility带有处理组件的能力呢?看下面的代码,在Facility加入容器时候,向容器注册了两个事件:
{
// 在组件创建之后引发
Kernel.ComponentModelCreated += new ComponentModelDelegate(OnComponentModelCreated);
// 在组件注册之后引发
Kernel.ComponentRegistered += new ComponentDataDelegate(OnComponentRegistered);
}
所以,下面的事情就是这样发生的了:
先Add一个组件,ComponentRegistered事件发生了。
在OnComponentRegistered中检查依赖性,如果依赖性满足并组件实现了IStartable的话,则请求创建这个组件。
{
object instance = Kernel[key];
}
创建组件的时候,ComponentModelCreated引发,在ComponentModelCreated中加入生命周期的处理事件,这里就用到了本文开头的两个实现了ILifecycleConcern的类:StartConcern和StopConcern。
把StartConcern注册为组件的LifecycleStepType.Commission(生命开始)周期处理行为。
把StopConcern注册为组件的LifecycleStepType.Decommission(生命结束)周期处理行为。
组件被创建之后,立刻进入LifecycleStepType.Commission周期,StartConcern被触发处理,StartConcern.Apply()调用组件的Start()来达到自启动的目的。
同样组件从容器移除的时候,组件就进入LifecycleStepType.Decommission,那么StopConcern.Apply()触发组件的Stop()来进行“最后的喘息”。
Startable的Facility设计原理已经说完,下步就实践咯。J
/// 这是一个实现IStartable的类,主要用Application.Run()启动一个窗口
/// 注意看他的构造函数
/// </summary>
public class ApplicationRunner : IStartable
{
private Form _form;
private Thread _thread;
// 这里表明:这个类是依赖于类型为Form1的组件的
public ApplicationRunner(Form1 form)
{
_form = form;
}
#region IStartable 成员
public void Start()
{
_thread = new Thread(new ThreadStart(StartApp));
_thread.Start();
}
public void Stop()
{
MessageBox.Show("Stop is called, but it do nothing.");
}
#endregion
private void StartApp()
{
Application.Run( _form );
}
}
其中Form1是一个普通窗口:
{
// ….
}
最后是Main:
static void Main()
{
// 建立容器
IWindsorContainer container = new WindsorContainer("../../AppConfig.xml");
// 加入Facility
container.AddFacility("startable", new StartableFacility());
// 加入一个ApplicationRunner,这时候容器检测到他对Form1有依赖,所以不启动
container.AddComponent("appRuner", typeof(ApplicationRunner));
// 加入Form1,此时ApplicationRunner满足依赖需求,Start就开始了
container.AddComponent("form1", typeof(Form1));
}
OK!这节就到这里,我想大家都清楚一个Facility的概念和用法了吧,有没有感觉到Facility的强大了?用他来@#$%*&组件吧,Bye~(下一节说点什么好呢?各位有建议吗?)