您的位置:首页 > 其它

我记录开源系统1.6源码解析(二)之IOC容器浅析

2012-01-16 21:56 381 查看
这篇为了进一步加深对我记录IOC管理容器的运行流程,我们继续分析ObjectContext这个类。主要是对InitInJect这个方

法继续分析。

private static void InitInject( ObjectContext ctx ) {
loadAssemblyAndTypes( ctx );
resolveAndInject( ctx );
addNamedObjects( ctx );
}



ObjectContext类位于wojilu项目的DI文件夹中,如图:





可以看到DI文件夹里包含MapItem和ObjectContext两个类。说明这两个类跟DI紧密关联。

第一行调用loadAssemblyAndTypes方法:

private static void loadAssemblyAndTypes( ObjectContext ctx ) {

String appSettings = cfgHelper.GetAppSettings( "InjectAssembly" );//读取web.config里的key为InjectAssembly的配置项
if (strUtil.IsNullOrEmpty( appSettings )) return;

String[] strArray = appSettings.Split( new char[] { ',' } );
foreach (String asmStr in strArray) {//遍历所有以","分割的程序集

if (strUtil.IsNullOrEmpty( asmStr )) continue;
String asmName = asmStr.Trim();
Assembly assembly = loadAssemblyPrivate(asmName, ctx);//加载web.config中的InjectAssembly,并加入ObjectContext
findTypesPrivate( assembly, asmName, ctx );
}
}

我们看看loadAssemblyPrivate这个方法:

/// <summary>
/// 根据程序集名称加载web.config中的InjectAssembly,并加入ObjectContext
/// </summary>
/// <param name="asmName">程序集名称</param>
/// <param name="ctx">容器实例</param>
/// <returns>返回程序集</returns>
private static Assembly loadAssemblyPrivate( String asmName, ObjectContext ctx ) {
Assembly assembly = Assembly.Load( asmName );//根据程序集名称加载程序集
ctx.AssemblyList.Add( asmName, assembly );//加入ObjectContext的AssemblyList(所有纳入容器管理的程序集)
return assembly;//返回程序集
}

接下来findTypesPrivate方法:

private static void findTypesPrivate( Assembly assembly, String asmName, ObjectContext ctx ) {
Type[] types = assembly.GetTypes();//返回程序集里定义的类型
ctx.AssemblyTypes.Add(asmName, types);//这里加入ObjectContext的AssemblyTypes属性,所有程序集名称,所有类型

foreach (Type type in types) {//遍历程序集下的所有类型
ctx.TypeList.Add(type.FullName, type);//这里加入InjectAssembly下的TypeList所有类型,所有纳入容器管理的类型
}
}

loadAssemblyAndTypes方法还是没什么很多的内容的,我们看看第二行的resolveAndInject( ctx ):

private static void resolveAndInject( ObjectContext ctx ) {
List<MapItem> maps = cdb.findAll<MapItem>();//查询所有依赖注入里的配置项
if (maps.Count <= 0) return;

Dictionary<String, MapItem> resolvedMap = new Dictionary<String, MapItem>();

logger.Info( "resolve item begin..." );//记录日志
resolveMapItem( maps, resolvedMap, ctx );//处理所有MapItem

logger.Info( "inject Object begin..." );
injectObjects( maps, resolvedMap );//resolvedMap,处理过的MapItem:wojilu.Web.Context.ContextInit

ctx.ResolvedMap = resolvedMap;
}


List<MapItem> maps = cdb.findAll<MapItem>();展开后涉及到比较多的代码,我们来把部分代码展开:

/// <summary>
/// 查询类型 T 的所有数据
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns>返回所有数据的列表</returns>
public static List<T> findAll<T>() where T : CacheObject {
IList list = MemoryDB.FindAll( typeof( T ) );//如wojilu.DI.MapItem
return db.getResults<T>( list );
}


这个方法在cdb类里:

/// <summary>
/// 从内存数据库中查询数据
/// </summary>
/// <remarks>
/// 数据持久化在 /framework/data/ 目录下,以json格式存储。加载之后常驻内存。
/// 特点:直接从内存中检索,速度相当于 Hashtable。插入和更新较慢(相对而言),因为插入和更新会在内存中重建索引。
/// </remarks>
public class cdb

cdb.findAll<T>()方法又会调用MemoryDB.FindAll(typeof(T)):

internal static IList FindAll( Type t ) {
return new ArrayList( GetObjectsByName( t ) );
}

GetObjectsByName(Type t)如下:

/// <summary>
/// 根据类型t得到以该类型t命名的配置文件中的所有类型
/// </summary>
/// <param name="t"></param>
/// <returns></returns>
private static IList GetObjectsByName( Type t ) {

if (isCheckFileDB( t )) {//是否应该检查配置文件

lock (chkLock) {

if (isCheckFileDB( t )) {

loadDataFromFile( t );//从配置文件加载类型t
_hasCheckedFileDB[t] = true;

}

}

}
return (objectList[t.FullName] as IList);
}

loadDataFromFile(Type t )方法如下:

/// <summary>
/// 从配置文件中加载所有类型
/// </summary>
/// <param name="t"></param>
private static void loadDataFromFile( Type t ) {
if (wojilu.IO.File.Exists( getCachePath( t ) )) {//检查以类型t命名的配置文件是否存在
IList list = getListWithIndex( wojilu.IO.File.Read( getCachePath( t ) ), t );
objectList[t.FullName] = list;
}
else {
objectList[t.FullName] = new ArrayList();
}
}


最主要是getListWithIndex( String jsonString, Type t )方法:

private static IList getListWithIndex( String jsonString, Type t ) {

IList list = new ArrayList();

if (strUtil.IsNullOrEmpty( jsonString )) return list;

List<object> lists = JsonParser.Parse( jsonString ) as List<object>;//解析json格式的数组,返回Dictionary类型的数组,包含Name,Type

foreach (Dictionary<String, object> map in lists) {//遍历

CacheObject obj = JSON.setValueToObject( t, map ) as CacheObject;//把json数组里的Type转换为t对象里的属性
int index = list.Add( obj );
addIdIndex( t.FullName, obj.Id, index );
makeIndexByInsert( obj );
}

return list;
}







 

至于resolveMapItem和injectObjects

private static void resolveMapItem( List<MapItem> maps, Dictionary<String, MapItem> resolvedMap, ObjectContext ctx )



private static void     injectObjects( List<MapItem> mapItems, Dictionary<String, MapItem> resolvedMap )






 

两个方法也是跟注入对象相关。我们最后来看下addNamedObjects方法:

private static void addNamedObjects( ObjectContext ctx ) {
Dictionary<String, MapItem> resolvedMap = ctx.ResolvedMap;
Hashtable namedObjects = new Hashtable();
foreach (KeyValuePair<String, MapItem> entry in resolvedMap) {
MapItem item = entry.Value;
namedObjects.Add( item.Name, item.TargetObject );
}
ctx.ObjectsByName = namedObjects;
}


这个很简单,把处理过的MapItem附给根据名称罗列的对象表(HashTable)。

总结:今后还得继续对wojilu的DI容器代码分析深入研究。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐