多數(shù)用戶都會(huì)將容器中的大部分對(duì)象布署為singleton模式,。當(dāng)一個(gè)singleton對(duì)象需要和另一個(gè)singleton對(duì)象協(xié)作,,或者一個(gè)非singleton對(duì)象需要和另一個(gè)非singleson對(duì)象協(xié)作時(shí),Spring.NET都能很好的處理它們的依賴關(guān)系,。但是,如果對(duì)象的生存周期不同,,就可能會(huì)產(chǎn)生問題,。例如,,假設(shè)一個(gè)singleton對(duì)象A要使用一個(gè)非singleton(原型)對(duì)象B,A中的每個(gè)方法都會(huì)用到B的新實(shí)例,。由于 A是singleton對(duì)象,,容器只有會(huì)創(chuàng)建它一次,也就是說只有一次給A的屬性賦值的機(jī)會(huì),,所以不可能在每次A需要的時(shí)候都給它注入一個(gè)新的B,。
有一種解決的辦法有點(diǎn)違背控制反轉(zhuǎn)原則:類A可以通過實(shí)現(xiàn)IObjectFactoryAware接口來獲取容器的引用,并調(diào)用GetObject("B")在每次需要的時(shí)候從容器中請(qǐng)求一個(gè)(新的)對(duì)象B,。但這并不是一個(gè)很好的解決方案,因?yàn)榭蛻舸a此時(shí)必須要和Spring.NET發(fā)生緊耦合,。
通過方法注入,,我們可以用更優(yōu)雅的方式解決類似的問題,。(摘自Spring.NET中文手冊(cè))
一、查詢方法注入
Spring.NET可以動(dòng)態(tài)覆蓋對(duì)象的抽象方法或虛方法,,并且可以在容器內(nèi)查找已命名對(duì)象,查詢方法注入就利用了這些功能。個(gè)人感覺查詢方法注入類似抽象工廠,,為之不同的是,,可以不用寫抽象的實(shí)現(xiàn)代碼,通過配置文件動(dòng)態(tài)的切換組件,。
在lookup-method節(jié)點(diǎn)配置name和object屬性
實(shí)現(xiàn)代碼如下:
<!--查詢方法--> <object id="personDao" type="SpringNet_MethodDi.PersonDao, SpringNet_MethodDi" singleton="false"/> <object id="objectFactory" type="SpringNet_MethodDi.ObjectFactory, SpringNet_MethodDi"> <lookup-method name="CreatePersonDao" object="personDao"/> </object>
LookupMethod
//注意,,可以直接在配置中定義這個(gè)類的對(duì)象 public abstract class ObjectFactory { //或者可以是一個(gè)虛方法 public abstract PersonDao CreatePersonDao(); } public class PersonDao { public void Save() { Console.WriteLine("保存數(shù)據(jù)"); } }
二、替換任意方法
替換任意方法在項(xiàng)目中使用的很少,,實(shí)現(xiàn)方法也比較復(fù)雜,。至于Spring.NET為什么使用替換任意方法,我還不是很清楚,,如果有知道使用場(chǎng)景的朋友可以給我留言,。我個(gè)人認(rèn)為其用途是:實(shí)現(xiàn)非派生類方法的重寫或在IoC框架中簡(jiǎn)易的AOP攔截(這一點(diǎn)又不確定,以后我會(huì)寫AOP方面的博客),。
首先繼承IMethodReplacer接口并實(shí)現(xiàn)Implement方法,,object[] arguments為傳入的參數(shù)。其次在replaced-method節(jié)點(diǎn)配置name和replacer屬性,,和增加arg-type節(jié)點(diǎn)且配置返回類型match屬性
代碼如下:
<!--替換方法--> <object id="userDao" type="SpringNet_MethodDi.UserDao, SpringNet_MethodDi"> <replaced-method name="GetValue" replacer="replaceValue"> <arg-type match="String"/> </replaced-method> </object> <object id="replaceValue" type="SpringNet_MethodDi.ReplaceValue, SpringNet_MethodDi"/>
ReplacedMethod
public class UserDao { //虛方法 public virtual string GetValue(string input) { return null; } } //實(shí)現(xiàn)IMethodReplacer接口 public class ReplaceValue : IMethodReplacer { public object Implement(object target, MethodInfo method, object[] arguments) { string value = (string)arguments[0]; return "獲取到:" + value; } }
三,、事件注入
在Spring.NET的IoC框架中,除了提供方法注入以外,,還提供事件的注入,。通過事件的注入,可以使架構(gòu)體系的耦合降到最低,。(參考 clingingboy的 Spring.NET學(xué)習(xí)筆記(3)-注冊(cè)事件注入)
在listener節(jié)點(diǎn)處配置event和method屬性指明事件名和綁定的方法,,并增加ref節(jié)點(diǎn)設(shè)置object屬性來指明調(diào)用哪個(gè)IoC容器對(duì)象。
實(shí)現(xiàn)代碼:
<!--事件注入--> <object id="men" type="SpringNet_MethodDi.Men, SpringNet_MethodDi"> <listener event="OpenTheDoor" method="OpenThisDoor"> <ref object="door"/> </listener> </object> <object id="door" type="SpringNet_MethodDi.Door, SpringNet_MethodDi" />
Listener
//先定義一個(gè)委托 public delegate string OpenHandler(string arg); public class Door { public event OpenHandler OpenTheDoor; public void OnOpen(string arg) { //調(diào)用事件 if (OpenTheDoor != null) { Console.WriteLine(OpenTheDoor(arg)); } } } public class Men { public string OpenThisDoor(string arg) { return "參數(shù)是:" + arg; } }
調(diào)用部分代碼:
Program
class Program { static void Main(string[] args) { IApplicationContext ctx = ContextRegistry.GetContext(); Console.WriteLine("查詢方法"); ObjectFactory factory = (ObjectFactory)ctx.GetObject("objectFactory"); factory.CreatePersonDao().Save(); Console.WriteLine(); Console.WriteLine("替換方法"); UserDao dao = (UserDao)ctx.GetObject("userDao"); Console.WriteLine(dao.GetValue("Liu Dong")); Console.WriteLine(); Console.WriteLine("事件注冊(cè)"); Door door = (Door)ctx.GetObject("door"); door.OnOpen("Opening!"); Console.WriteLine(); Console.ReadLine(); } }
輸入效果:
|