今天有一个“27745754”的朋友对Castle IOC容器的自动装配提出了疑问,如果有多个类(组件)实现同一个接口(服务),它会自动选择哪个来进行装配?很多朋友应该都有这样的问题,这里特别说明一下。
还是以我在Castle IOC容器快速入门里用到的日志记录组件为例,现在我们对于ILogFormatter接口:
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
/**//// <summary>
![](/Images/OutliningIndicators/InBlock.gif)
/// Author:Terrylee
![](/Images/OutliningIndicators/InBlock.gif)
/// From:http://terrylee.cnblogs.com
![](/Images/OutliningIndicators/InBlock.gif)
/// </summary>![](/Images/OutliningIndicators/None.gif)
public interface ILogFormatter
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
string Format(string MsgStr);
}
它有两个实现,分别为:TextFormatter和PlanFormatter:
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
/**//// <summary>
![](/Images/OutliningIndicators/InBlock.gif)
/// Author:Terrylee
![](/Images/OutliningIndicators/InBlock.gif)
/// From:http://terrylee.cnblogs.com
![](/Images/OutliningIndicators/InBlock.gif)
/// </summary>![](/Images/OutliningIndicators/None.gif)
public class TextFormatter : ILogFormatter
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
public TextFormatter()
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](/Images/OutliningIndicators/InBlock.gif)
}
![](/Images/OutliningIndicators/InBlock.gif)
public string Format(string MsgStr)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
return "[" + MsgStr + "]";
}
}
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
/**//// <summary>
![](/Images/OutliningIndicators/InBlock.gif)
/// Author:Terrylee
![](/Images/OutliningIndicators/InBlock.gif)
/// From:http://terrylee.cnblogs.com
![](/Images/OutliningIndicators/InBlock.gif)
/// </summary>![](/Images/OutliningIndicators/None.gif)
public class PlanFormatter : ILogFormatter
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
public PlanFormatter()
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](/Images/OutliningIndicators/InBlock.gif)
}
![](/Images/OutliningIndicators/InBlock.gif)
public string Format(string MsgStr)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
return "{" + MsgStr + "}";
}
}
再来看一下,在日志记录组件中,它依赖于ILogFormatter
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
/**//// <summary>
![](/Images/OutliningIndicators/InBlock.gif)
/// Author:Terrylee
![](/Images/OutliningIndicators/InBlock.gif)
/// From:http://terrylee.cnblogs.com
![](/Images/OutliningIndicators/InBlock.gif)
/// </summary>![](/Images/OutliningIndicators/None.gif)
public class TextFileLog : ILog
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
private string _target;
![](/Images/OutliningIndicators/InBlock.gif)
private ILogFormatter _format;
![](/Images/OutliningIndicators/InBlock.gif)
public TextFileLog(string target,ILogFormatter format)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
this._target = target;
![](/Images/OutliningIndicators/InBlock.gif)
this._format = format;
}
![](/Images/OutliningIndicators/InBlock.gif)
public void Write(string MsgStr)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
string _MsgStr = _format.Format(MsgStr);
![](/Images/OutliningIndicators/InBlock.gif)
_MsgStr += _target;
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
//Output Message
![](/Images/OutliningIndicators/InBlock.gif)
Console.WriteLine("Output "+_MsgStr);
}
}
那么当我们在容器中加入组件后,它会自动装配TextFormatter还是PlanFormatter呢?以事实说话,先来看一下运行的结果吧:
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
/**//// <summary>
![](/Images/OutliningIndicators/InBlock.gif)
/// Author:Terrylee
![](/Images/OutliningIndicators/InBlock.gif)
/// From:http://terrylee.cnblogs.com
![](/Images/OutliningIndicators/InBlock.gif)
/// </summary>![](/Images/OutliningIndicators/None.gif)
public class App
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
public static void Main()
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
//建立容器
![](/Images/OutliningIndicators/InBlock.gif)
IWindsorContainer container = new WindsorContainer( new XmlInterpreter("http://www.cnblogs.com/BasicUsage.xml") );
![](/Images/OutliningIndicators/InBlock.gif)
//加入组件
![](/Images/OutliningIndicators/InBlock.gif)
container.AddComponent("txtLog",
![](/Images/OutliningIndicators/InBlock.gif)
typeof(ILog), typeof(TextFileLog));
![](/Images/OutliningIndicators/InBlock.gif)
container.AddComponent("planformat",
![](/Images/OutliningIndicators/InBlock.gif)
typeof(ILogFormatter), typeof(PlanFormatter));
![](/Images/OutliningIndicators/InBlock.gif)
container.AddComponent("txtformat",
![](/Images/OutliningIndicators/InBlock.gif)
typeof(ILogFormatter), typeof(TextFormatter));
![](/Images/OutliningIndicators/InBlock.gif)
//获取组件
ILog log = (ILog) container["txtLog"];
![](/Images/OutliningIndicators/InBlock.gif)
//使用组件
log.Write("First Castle IOC Demo");
![](/Images/OutliningIndicators/InBlock.gif)
Console.ReadLine();
}
}
![](/Images/OutliningIndicators/None.gif)
运行程序,结果如下:
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
Output
{First Castle IOC Demo}log.txt
也就是说,它自动装配了PlanFormatter,再调整一下加入组件到容器中的顺序:
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
/**//// <summary>
![](/Images/OutliningIndicators/InBlock.gif)
/// Author:Terrylee
![](/Images/OutliningIndicators/InBlock.gif)
/// From:http://terrylee.cnblogs.com
![](/Images/OutliningIndicators/InBlock.gif)
/// </summary>![](/Images/OutliningIndicators/None.gif)
public class App
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
public static void Main()
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
// 建立容器
IWindsorContainer container = new WindsorContainer( new XmlInterpreter("http://www.cnblogs.com/BasicUsage.xml") );
![](/Images/OutliningIndicators/InBlock.gif)
// 加入组件
container.AddComponent("txtLog",
![](/Images/OutliningIndicators/InBlock.gif)
typeof(ILog), typeof(TextFileLog));
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
// 注意这里调整了顺序
container.AddComponent("txtformat",
![](/Images/OutliningIndicators/InBlock.gif)
typeof(ILogFormatter), typeof(TextFormatter));
![](/Images/OutliningIndicators/InBlock.gif)
container.AddComponent("planformat",
![](/Images/OutliningIndicators/InBlock.gif)
typeof(ILogFormatter), typeof(PlanFormatter));
![](/Images/OutliningIndicators/InBlock.gif)
// 获取组件
ILog log = (ILog) container["txtLog"];
![](/Images/OutliningIndicators/InBlock.gif)
// 使用组件
log.Write("First Castle IOC Demo");
![](/Images/OutliningIndicators/InBlock.gif)
Console.ReadLine();
}
}
再次运行,出现了下面的结果:
Output [First Castle IOC Demo]log.txt
这次自动装配的是TextFormatter。由这两次的结果我们可以得出:
如果有多个类(组件)实现同一个接口(服务),容器会自动选择最先加入到容器中的组件来装配。对于这样的结果,其实我们并不感觉到意外,每次注册组件时,容器都会检测它的依赖性,当加入第一个ILogFormatter的组件时,容器检测到TextFileLog已经满足了它的依赖性,所以它不会再去装配第二个。
相关参考:
Castle IOC容器快速入门
Castle IOC容器内幕故事(上)
Castle IOC容器内幕故事(下)