Castle实践2-Startable Facility

  这一节我们来分析Facility,作为Castle的可扩展单元,他是可以带有注入性的,也就是对组件来说,他可能“侵犯”组件本身。下面我们从官方提供的一个StartableFacility开始。


先明白这个Facility的作用,也就是要达到的目的:使一个实现了Castle.Model.IStartable接口的程序在满足依赖性的时候,能够自我执行。

public interface IStartable
{
    
void Start();      // 创建的时候执行
    void Stop();       // 销毁的时候执行
}


首先我们来了解一下这个接口:ILifecycleConcern,这个接口带有一个方法:

public interface ILifecycleConcern
{
    
void Apply( ComponentModel model, object component );
}


他用来在组件特定的生命周期提供处理行为。

比如,我们上一节提到的,实现了IInitializable接口的组件,容器会自动调用组件的初始化方法Initialize,只是执行这个接口的Facility是内置的(Kernel自带)。

接着,我们来用两个类实现这个接口:

第一个StartConcern,处理:如果是实现IStartable的组件则调用其Start()方法:

public void Apply(ComponentModel model, object component)
{
    (component 
as IStartable).Start();
}


第二个StopConcern,处理:如果实现IStartable的组件则调用其Stop()方法:

public void Apply(ComponentModel model, object component)
{
    (component 
as IStartable).Stop();
}


先别问为什么,知道功能就好,下面会继续讲到。
 

好了,我们看下如何实现一个Facility,创建一个自定的Facility可以直接实现IFacility接口,或者从AbstractFacility中继承下来,他们的不同支出只是AbstractFacility提供了IFacility接口的默认实现,你只需实现Init()方法即可。但其实IFacility包含的东西并不多,只有两个:

public interface IFacility
{
    
// Facility被添加到容器中就立刻执行
    void Init(IKernel kernel, IConfiguration facilityConfig);
    
// 一般在容器的Dispose()中被调用
    void Terminate();
}


既然我们要达到程序的自启动,好自然,我们应该在组件加入容器的时候检查其依赖性满足后就启动他。那么如何让自定的Facility带有处理组件的能力呢?看下面的代码,在Facility加入容器时候,向容器注册了两个事件:

protected override void Init()
{
    
// 在组件创建之后引发
    Kernel.ComponentModelCreated += new ComponentModelDelegate(OnComponentModelCreated);
    
// 在组件注册之后引发
    Kernel.ComponentRegistered += new ComponentDataDelegate(OnComponentRegistered);
}

所以,下面的事情就是这样发生的了:

Add一个组件,ComponentRegistered事件发生了。

OnComponentRegistered中检查依赖性,如果依赖性满足并组件实现了IStartable的话,则请求创建这个组件。

private void Start(String key)
{
    
object instance = Kernel[key];
}


创建组件的时候,ComponentModelCreated引发,在ComponentModelCreated中加入生命周期的处理事件,这里就用到了本文开头的两个实现了ILifecycleConcern的类:StartConcernStopConcern

StartConcern注册为组件的LifecycleStepType.Commission(生命开始)周期处理行为。

StopConcern注册为组件的LifecycleStepType.Decommission(生命结束)周期处理行为。

组件被创建之后,立刻进入LifecycleStepType.Commission周期,StartConcern被触发处理,StartConcern.Apply()调用组件的Start()来达到自启动的目的。

同样组件从容器移除的时候,组件就进入LifecycleStepType.Decommission,那么StopConcern.Apply()触发组件的Stop()来进行“最后的喘息”。

StartableFacility设计原理已经说完,下步就实践咯。J 

/// <summary>
/// 这是一个实现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是一个普通窗口:

public class Form1 : System.Windows.Forms.Form
{
    
// ….
}


最后是Main

[MTAThread]
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~(下一节说点什么好呢?各位有建议吗?)

原文地址:https://www.cnblogs.com/wj/p/179476.html