『Spring.NET』IoC 中方法的注入
主要参考:Spring.NET
什么时候使用方法的注入?
…………………………………………………………
In most application scenarios, most object in the container are singletons. When a singleton object needs to collaborate with another singleton object, or a non-singleton object needs to collaborate with another non-singleton object, you typically handle the dependency by defining one object as a property of the other. A problem arrises when the object lifecycles are different. Suppose singleton object A needs to use a non-singleton (prototype) object B, perhaps on each method invocation on A. The container only creates the singleton object A once, and thus only gets one opportunity to set the properties. The container cannot provide object A with a new instance of object B every time one is needed.
A solution is to forego some inversion of control. You can make object A aware of the container by implementing the IApplicationContextAware interface, and by making a GetObject("B") call to the container ask for (a typically new) object B every time it needs it.—— Spring.NET
多数用户都会将容器中的大部分对象布署为singleton模式。当一个singleton对象需要和另一个singleton对象协作,或者一个非singleton对象需要和另一个非singleson对象协作时,Spring.NET都能很好的处理它们的依赖关系。但是,如果对象的生存周期不同,就可能会产生问题。例如,假设一个singleton对象A要使用一个非singleton(原型)对象B,A中的每个方法都会用到B的新实例。由于A是singleton对象,容器只有会创建它一次,也就是说只有一次给A的属性赋值的机会,所以不可能在每次A需要的时候都给它注入一个新的B。
有一种解决的办法有点违背控制反转原则:类A可以通过实现IObjectFactoryAware接口来获取容器的引用,并调用GetObject("B")在每次需要的时候从容器中请求一个(新的)对象B。但这并不是一个很好的解决方案,因为客户代码此时必须要和Spring.NET发生紧耦合。
通过方法注入,我们可以用更优雅的方式解决类似的问题。——@刘冬.NET
在我理解,当我们要给一个singleton的对象注入一个prototype的对象时,为了保证松耦合以及其可用性,我们就可以使用这个方法的注入。
怎么使用方法的注入?
……………………………………………………
第一类方法注入——查询方法注入
在配置文件中:
1 <!-- a stateful object deployed as a prototype (non-singleton) -->
2 <object id="command" class="Fiona.Apple.AsyncCommand, Fiona" singleton="false">
3 <!-- inject dependencies here as required -->
4 </object>
5
6 <!-- commandProcessor uses a statefulCommandHelpder -->
7 <object id="commandManager" type="Fiona.Apple.CommandManager, Fiona">
8 <lookup-method name="CreateCommand" object="command"/>
9 </object>
在具体的类中:
1 using System.Collections;
2
3 namespace Fiona.Apple
4 {
5 public abstract class CommandManager
6 {
7
8 public object Process(IDictionary commandState)
9 {
10 Command command = CreateCommand();
11 command.State = commandState;
12 return command.Execute();
13 }
14
15 // okay... but where is the implementation of this method?
16 protected abstract Command CreateCommand();
17 }
18 }
说明:
- 配置文件中,使用<lookup-method name="CreateCommand" object="command"/>声明注入的方式
- name是要查询的方法的名字;object是要注入的在配置文件中声明的对象id,也是注入方法的返回值类型。
- CreateCommand必须是抽象的,也就是说等待注入的方法必须是抽象的,含有等待注入方法的类必须是抽象的。
第二类方法注入——替换任意方法
在配置文件中:
1 <object id="myValueCalculator" type="Examples.MyValueCalculator, ExampleAssembly">
2 <!-- arbitrary method replacement -->
3 <replaced-method name="ComputeValue" replacer="replacementComputeValue">
4 <arg-type match="String"/>
5 </replaced-method>
6 </object>
7
8 <object id="replacementComputeValue" type="Examples.ReplacementComputeValue, ExampleAssembly"/>
在具体的类中:
1 public class MyValueCalculator {
2
3 public virtual string ComputeValue(string input) {
4 // ... some real code
5 }
6
7 // ... some other methods
8 }
1 /// <summary>
2 /// Meant to be used to override the existing ComputeValue(string)
3 /// implementation in MyValueCalculator.
4 /// </summary>
5 public class ReplacementComputeValue : IMethodReplacer
6 {
7 public object Implement(object target, MethodInfo method, object[] arguments)
8 {
9 // get the input value, work with it, and return a computed result...
10 string value = (string) arguments[0];
11 // compute...
12 return result;
13 }
14 }
说明:
- 等待替换的方法必须是virtual方法,也就是虚方法。
- 实现类中的IMethodReplacer是必须的。
- public object Implement(object target, MethodInfo method, object[] arguments) 是固定的。
- arguments是用于接收ComputeValue中传入的参数input的,如果ComputeValue有多个参数,Implement也会有对应顺序的值保存在arguments中。
- result不是固定的,这个要根据ComputeValue来确定。
版权声明:
作者:莫不逢
出处:http://www.cnblogs.com/sitemanager/
Github:https://github.com/congjf
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。