zoukankan      html  css  js  c++  java
  • 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~(下一节说点什么好呢?各位有建议吗?)

  • 相关阅读:
    Kafka简介
    Storm之详解spout、blot
    【刷题】面筋-页面很卡的原因分析及解决方案
    【JAVA】栈和堆,JVM内存概述
    【刷题】面筋-游戏测试-农药测试向分析
    【刷题】面筋-游戏测试-什么样的游戏可以称为一个好的游戏
    【刷题】面筋-两颗鸡蛋测临界楼层的问题
    【刷题】面筋-游戏测试的目的和流程
    【刷题】面筋-测开-游戏测试用例要点与测试俄罗斯方块
    【刷题】面筋-游戏平衡性
  • 原文地址:https://www.cnblogs.com/wj/p/179476.html
Copyright © 2011-2022 走看看