Spring.Net IoC容器+Observer模式
欣喜地看到使用Spring.Net的人越来越多了,网络上介绍Spring.Net的文章也多了起来,不过看来看去,初级的例子总逃不掉Martin Fowler的那个MovieFinder-MovieList,本人自己写了另一个例子,并加入了用Delegate-Event实现的Observer模式,而Subject与Observer的绑定使用IoC Container和属性注入完成,可供大家参考。
Observer模式大家应已熟悉,故此处不多做阐述,首先是自定义的事件参数类型与Delegate定义的EventHandler
... {
private ArrayList arl = new ArrayList();
public object this[int index]
...{
get
...{
if (index >= arl.Count)
return null;
else
return arl[index];
}
set
...{
if (index >= arl.Count)
arl.Add(value);
else
arl[index] = value;
}
}
public int Count
...{
get
...{
return arl.Count;
}
}
}
public delegate void ObserverEventHandler(Object source, IObserverEventArgs eargs);
下面是Subject的实现
... {
void registerobserver(IObserver ob);
void removeobserver(IObserver ob);
void triggerevent(IObserverEventArgs oea);
}
public class Subject : ISubject
... {
private event ObserverEventHandler evhdl;
private IObserver _Observer;
public IObserver Observer
...{
set
...{
_Observer = value;
evhdl += new ObserverEventHandler(new ObserverEventHandler(((IObserver)value).RecieveEvent));
}
}
public void registerobserver(IObserver ob)
...{
evhdl += new ObserverEventHandler(new ObserverEventHandler(ob.RecieveEvent));
}
public void removeobserver(IObserver ob)
...{
evhdl -= (ObserverEventHandler)(ob.RecieveEvent);
}
public void triggerevent(IObserverEventArgs oea)
...{
this.evhdl(this,oea);
}
}
接下来是Observer的实现
... {
void RecieveEvent(object obj, IObserverEventArgs ea);
}
public class Observer : IObserver
... {
private static int id;
private int id_instance;
public Observer()
...{
id_instance = ++id;
}
public void RecieveEvent(Object obj, IObserverEventArgs oea)
...{
Console.WriteLine("Observer{0} is triggered!", id_instance);
for(int i = 0; i<oea.Count; i++)
Console.WriteLine("Parameters[{0}]: {1}",i,oea[i].ToString());
}
}
好了,综上,我们传统的Observer模式的创建便告一段落,接下来我们用Spring.Net的IoC Container(IApplicationContext)来在运行时创建加载配置在文件中的类,并用属性注入的方式对其进行依赖绑定。
首先是配置文件:
< configuration >
< configSections >
< sectionGroup name = " spring " >
< section name = " context " type = " Spring.Context.Support.ContextHandler, Spring.Core " />
< section name = " objects " type = " Spring.Context.Support.DefaultSectionHandler, Spring.Core " />
</ sectionGroup >
</ configSections >
< spring >
< context >
< resource uri = " config://spring/objects " />
</ context >
< objects xmlns = " http://www.springframework.net " >
< description > An example of Spring + Observer </ description >
< object name = " subject " type = " RichardObserverPattern.Subject, MandyObserverPattern " >
< property name = " Observer " ref = " observer1 " />
</ object >
< object name = " observer1 " type = " RichardObserverPattern.Observer, MandyObserverPattern " />
</ objects >
</ spring >
</ configuration >
其次是客户端的调用:
... {
static void Main(string[] args)
...{
Program p = new Program();
p.RunningTrunk();
}
public void RunningTrunk()
...{
IApplicationContext ctx = ContextRegistry.GetContext();
ISubject sb = (ISubject)ctx.GetObject("subject");
IObserverEventArgs oea = new ObserverEventArgs();
oea[0] = "1";
oea[1] = "2";
sb.triggerevent(oea);
Console.ReadLine();
}
}
我们在这里实实在在地体会到了Spring.Net给我们带来的方便与快捷,不仅如此,还有良好的可扩展与松耦合。
在此需要声明的一点是,此例作为学习用例虽让Subject与Observer进行了较紧密的耦合,但在实际实践中Subject与Observer的关系却应该更松一些,也就是只通过Delegate建立方法间的绑定,而非类级别的。另外作为.Net的功能来讲,Delegate乃是其特有的的优秀之处,所以我建议Spring.Net的作者能够在属性注入和构造器注入之外增加方法注入和委托注入,以支持类之间的轻量级的装订与拆卸。