博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Castle IOC容器实践之Startable Facility(二)
阅读量:7221 次
发布时间:2019-06-29

本文共 4349 字,大约阅读时间需要 14 分钟。

摘要:在Castle IOC容器实践之Startable Facility(一)中我们已经学会了如何去使用Startable Facility,本文将在此基础进一步对它的原理做一些分析。

 
主要内容
Startable Facility
原理分析
……
 
Castle IOC容器实践之Startable Facility(一)中我们已经看到了如何去使用Startable Facility,本文将对它的原理做一些分析。先看一下接口IStartable,它的实现代码如下:
None.gif
public
 
interface
 IStartable
ExpandedBlockStart.gif
{
InBlock.gif    
void Start();
InBlock.gif
InBlock.gif    
void Stop();
ExpandedBlockEnd.gif}
代码是相当的简单,只有两个方法,分别在组件创建的时候和销毁的时候执行,这就涉及到了组件的生命周期管理。在 Windsor中,接口
ILifecycleConcern
提供特定的组件生命周期管理:
None.gif
public
 
interface
 ILifecycleConcern
ExpandedBlockStart.gif
{
InBlock.gif    
void Apply( ComponentModel model, object component );
InBlock.gif
ExpandedBlockEnd.gif}
现在我们要实现组件的自动创建和销毁,就需要实现接口
ILifecycleConcern
,在
Startable Facility
中分别用两个类来实现,第一个类StartConcern,它判断如果组件实现了接口IStartable,则直接调用它的Start()方法;如果组件是用特性startMethod,则获取并调用具有startMethod特性的方法:
None.gif
public
 
class
 StartConcern : ILifecycleConcern
ExpandedBlockStart.gif
{
InBlock.gif    
private static readonly StartConcern _instance = new StartConcern();
InBlock.gif
InBlock.gif    
protected StartConcern()
ExpandedSubBlockStart.gif    
{
InBlock.gif
ExpandedSubBlockEnd.gif    }
InBlock.gif
InBlock.gif    
public static StartConcern Instance
ExpandedSubBlockStart.gif    
{
ExpandedSubBlockStart.gif        
get return _instance; }
ExpandedSubBlockEnd.gif    }
InBlock.gif
InBlock.gif    
public void Apply(ComponentModel model, object component)
ExpandedSubBlockStart.gif    
{
InBlock.gif        
if (component is IStartable)
ExpandedSubBlockStart.gif        
{
InBlock.gif            (component 
as IStartable).Start();
ExpandedSubBlockEnd.gif        }
InBlock.gif        
else if (model.Configuration != null)
ExpandedSubBlockStart.gif        
{
InBlock.gif            String startMethod 
= model.Configuration.Attributes["startMethod"];
InBlock.gif 
InBlock.gif            
if (startMethod != null)
ExpandedSubBlockStart.gif            
{
InBlock.gif
InBlock.gif                MethodInfo method 
= model.Implementation.GetMethod(startMethod);
InBlock.gif
InBlock.gif                method.Invoke(component, 
null);
ExpandedSubBlockEnd.gif            }
ExpandedSubBlockEnd.gif        }
ExpandedSubBlockEnd.gif    }
ExpandedBlockEnd.gif}
第二个类是
StopConcern
,它判断如果组件实现了接口IStartable,则直接调用它的Stop()方法;如果组件是用特性stopMethod,则获取并调用具有stopMethod特性的方法:
None.gif
public
 
class
 StopConcern : ILifecycleConcern
ExpandedBlockStart.gif
{
InBlock.gif    
private static readonly StopConcern _instance = new StopConcern();
InBlock.gif
InBlock.gif    
protected StopConcern()
ExpandedSubBlockStart.gif    
{
InBlock.gif
ExpandedSubBlockEnd.gif    }
InBlock.gif
InBlock.gif    
public static StopConcern Instance
ExpandedSubBlockStart.gif    
{
ExpandedSubBlockStart.gif        
get return _instance; }
ExpandedSubBlockEnd.gif    }
InBlock.gif
InBlock.gif    
public void Apply(ComponentModel model, object component)
ExpandedSubBlockStart.gif    
{
InBlock.gif        
if(component is IStartable)
ExpandedSubBlockStart.gif        
{
InBlock.gif            (component 
as IStartable).Stop();
ExpandedSubBlockEnd.gif        }
InBlock.gif        
else if (model.Configuration != null)
ExpandedSubBlockStart.gif        
{
InBlock.gif            String stopMethod 
= model.Configuration.Attributes["stopMethod"];
InBlock.gif
InBlock.gif            
if (stopMethod != null)
ExpandedSubBlockStart.gif            
{
InBlock.gif                MethodInfo method 
= model.Implementation.GetMethod(stopMethod);
InBlock.gif
InBlock.gif                method.Invoke(component, 
null);
ExpandedSubBlockEnd.gif            }
ExpandedSubBlockEnd.gif        }
ExpandedSubBlockEnd.gif    }
ExpandedBlockEnd.gif}
好了,知道了 Startable Facility如何管理组件的生命周期,我们就来看看真正的 Startable Facility是如何实现的。每一个 Facility都是满足这样的一个继承关系:
1 Facility继承关系图
其中的Abstract Facility提供了一些默认的实现,Facility可以直接实现IFacility,也可以继承于Abstract FacilityIFacility的实现如下:
None.gif
public
 
interface
 IFacility
ExpandedBlockStart.gif
{
InBlock.gif    
void Init(IKernel kernel, IConfiguration facilityConfig);
InBlock.gif
InBlock.gif
InBlock.gif    
void Terminate();
InBlock.gif
ExpandedBlockEnd.gif}
那么到底如何让组件满足依赖性后就自动执行呢?注意到再 Startable Facility的 Init()注册了这样的两个事件:
None.gif
protected
 
override
 
void
 Init()
ExpandedBlockStart.gif
{
InBlock.gif    converter 
= (ITypeConverter) Kernel.GetSubSystem(SubSystemConstants.ConversionManagerKey);
InBlock.gif
InBlock.gif
InBlock.gif    Kernel.ComponentModelCreated 
+= 
InBlock.gif
InBlock.gif        
new ComponentModelDelegate(OnComponentModelCreated);
InBlock.gif
InBlock.gif    Kernel.ComponentRegistered 
+= 
InBlock.gif
InBlock.gif        
new ComponentDataDelegate(OnComponentRegistered);
InBlock.gif
ExpandedBlockEnd.gif}
 
分别为OnComponentModelCreatedOnComponentRegistered。当我们注册一个组件时首先会出发OnComponentRegistered事件,在它里面判断组件是否满足依赖性,如果不满足,则添加到一个等待列表中,否则就直接启动,然后再对这个等待列表进行检测,看添加改组件后,列表中是否有组件满足了依赖性:
None.gif
private
 
void
 OnComponentRegistered(String key, IHandler handler)
ExpandedBlockStart.gif
{
InBlock.gif    
bool startable = (bool) handler.ComponentModel.ExtendedProperties["startable"];
InBlock.gif
InBlock.gif    
if (startable)
ExpandedSubBlockStart.gif    
{
InBlock.gif        
if (handler.CurrentState == HandlerState.WaitingDependency)
ExpandedSubBlockStart.gif        
{
InBlock.gif            waitList.Add( handler );
ExpandedSubBlockEnd.gif        }
InBlock.gif        
else
ExpandedSubBlockStart.gif        
{
InBlock.gif            Start( key );
ExpandedSubBlockEnd.gif        }
ExpandedSubBlockEnd.gif    }
InBlock.gif
InBlock.gif    CheckWaitingList();
ExpandedBlockEnd.gif}
None.gif
None.gif
private
 
void
 CheckWaitingList()
ExpandedBlockStart.gif
{
InBlock.gif    IHandler[] handlers 
= (IHandler[]) waitList.ToArray( typeof(IHandler) );
InBlock.gif
InBlock.gif    IList validList 
= new ArrayList();
InBlock.gif
InBlock.gif    
foreach(IHandler handler in handlers)
ExpandedSubBlockStart.gif    
{
InBlock.gif        
if (handler.CurrentState == HandlerState.Valid)
ExpandedSubBlockStart.gif        
{
InBlock.gif            validList.Add(handler);
InBlock.gif
InBlock.gif            waitList.Remove(handler);
ExpandedSubBlockEnd.gif        }
ExpandedSubBlockEnd.gif    }
InBlock.gif
InBlock.gif    
foreach(IHandler handler in validList)
ExpandedSubBlockStart.gif    
{
InBlock.gif        Start( handler.ComponentModel.Name );
ExpandedSubBlockEnd.gif    }
ExpandedBlockEnd.gif}
刚才说到,如果满足了依赖性,则会请求创建这个组件:
None.gif
private
 
void
 Start(String key)
ExpandedBlockStart.gif
{
InBlock.gif    
object instance = Kernel[key];
ExpandedBlockEnd.gif}
这时就触发了 OnComponentModelCreated事件,这时就该用到开始我们所讲的那两生命周期处理的类了:
None.gif
private
 
void
 OnComponentModelCreated(ComponentModel model)
ExpandedBlockStart.gif
{
InBlock.gif    
bool startable = 
InBlock.gif
InBlock.gif        CheckIfComponentImplementsIStartable(model) 
|| HasStartableAttributeSet(model);
InBlock.gif
InBlock.gif    model.ExtendedProperties[
"startable"= startable;
InBlock.gif
InBlock.gif    
if (startable)
ExpandedSubBlockStart.gif    
{
InBlock.gif        model.LifecycleSteps.Add( 
InBlock.gif
InBlock.gif            LifecycleStepType.Commission, StartConcern.Instance );
InBlock.gif
InBlock.gif        model.LifecycleSteps.Add( 
InBlock.gif
InBlock.gif            LifecycleStepType.Decommission, StopConcern.Instance );
InBlock.gif
ExpandedSubBlockEnd.gif    }
ExpandedBlockEnd.gif}
首先还是先判断组件是否实现了 IStartable接口或这时候有特性 startable,如果没有那也就不用自动启动了,否则就把 StartConcern和 StopConcern分别注册为组件的生命周期开始行为和生命周期结束行为,(关于组件的生命周期的详细内容可以参考我前面写的 Castle IOC容器组件生命周期管理)。此时组件进入生命周期开始,会调用 StartConcern的 Apply()方法,这时就触发组件的 Start()方法,同样在组件销毁时调用 StopConcern的 Apply()方法,这时就会调用组件的 Stop()方法。这样就完成整个了组件的自动执行与销毁的全过程。
本文转自lihuijun51CTO博客,原文链接: http://blog.51cto.com/terrylee/67685
,如需转载请自行联系原作者
你可能感兴趣的文章
GitHub发布Python安全警告 识别依赖包的安全漏洞
查看>>
讲好文创的时代故事
查看>>
支持53种语言预训练模型,斯坦福发布全新NLP工具包StanfordNLP
查看>>
翟欣欣微博发声解释“真相”
查看>>
Mac 常用必备软件(GitHub)
查看>>
快速排序就这么简单
查看>>
老腊肉级干货 | OOD面试备战攻略
查看>>
Google 回归中国,你准备好成为 Googler 了吗?
查看>>
React Native 项目(One 【一个】客户端)
查看>>
万套源码分享系列一
查看>>
util.promisify 的那些事儿
查看>>
vue3.0 尝鲜 -- 摒弃 Object.defineProperty,基于 Proxy 的观察者机制探索
查看>>
PHP 文件操作的各种姿势
查看>>
Linux 探索之旅 | 第一部分第六课:Linux 如何安装在虚拟机中
查看>>
Jquery第一篇【介绍Jquery、回顾JavaScript代码、JS对象与JQ对象的区别】
查看>>
【火炉炼AI】机器学习039-NLP文本分类器
查看>>
java通过JDBC链接SQLServer2012【转载!!!超详细】
查看>>
cmake使用教程(八)-macro和function
查看>>
掘金广告产品介绍
查看>>
小猪的Python学习之旅 —— 7.Python并发之threading模块(1)
查看>>