ESFramework中很多重要的组件都配备了日志记录器IEsbLogger,用于记录框架运行时的错误和异常。这些重要组件都暴露了一个名为“EsbLogger”的属性,用于设值法注入日志记录器。
在构建应用时,我采用Spring.net进行组件装配,在Spring的XML配置文件中,需要为这些重要组件配置“EsbLogger”属性,为了不遗漏、配置不错误,手动装配时必须非常小心,甚至是我自己,也得如此。因为在数百个组件中,我也记不得哪些组件配备了IEsbLogger,哪些没有。如果能自动为需要的组件装配日志记录器就好了--这个是可以做到的。能达到这个目的是因为我们已经具备了两个前提:
(1)如果ESFramework中的一个组件需要日志记录器,它都会暴露一个名为“EsbLogger”的属性。
(2)Spring容器提供了一种间接的方法让我们遍历容器中的每一个对象。
如果能自动装配日志记录器,那么Spring配置文件中就可以不用理会任何组件的日志记录器的装配了,世界将变得简单些。
首先,我们获取Spring容器中的所有对象的list:
ArrayList objList = new ArrayList() ;
string[] names = MainClass.SpringContext.GetObjectDefinitionNames() ;
foreach(string name in names)
{
objList.Add(MainClass.SpringContext.GetObject(name)) ;
}
接下来,写一个可重用的方法,用于为list中的每个对象设置指定的属性,如果某个对象没有指定的属性,则跳过:
public static void SetProperty(IList objs ,string propertyName ,object proValue)
{
object[] args = {proValue} ;
foreach(object target in objs)
{
Type t = target.GetType() ;
if(t.GetProperty(propertyName) == null)
{
continue ;
}
t.InvokeMember(propertyName ,BindingFlags.Default | BindingFlags.SetProperty ,null ,target ,args) ;
}
}
到了这里,已经水到渠成了:
//获取日志记录器组件
object esbLogger = MainClass.SpringContext.GetObject("esbLogger") ;
//装配
SetProperty(objList ,"EsbLogger" ,esbLogger) ;
如果以后ESFramework中的某个组件需要装配日志记录器而新添了“EsbLogger”属性,那么我们的Spring配置文件也不用做任何更改了,运行时会自动装配它。
这种自动装配日志记录器的方案并不是全面适用,因为它依赖Spring容器,如果我们基于ESFramework构建的应用中没有使用类似Spring的IOC容器,那么该怎么做了?
答案,我还没找到,因为如果没有容器,我该如何获取当前应用中的所有对象了?不能得到所有的对象,就无法利用上述的反射来为之动态装配日志记录器。
之前,我还想到过一方案,就是稍微修改ESFramework中每个需要配备日志记录器的组件的实现,让它们的对象在创建的时候向公共的Util注册(可以在组件的构造函数中进行注册),这样就可以从Util获取对象列表了,但是这种方案有太强的侵入性,并且使每个组件都依赖与Util,所以放弃了这种方案。