zoukankan      html  css  js  c++  java
  • 我记录开源系统1.6源码解析(二)之IOC容器浅析

    这篇为了进一步加深对我记录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容器代码分析深入研究。

  • 相关阅读:
    一些鲜为人知的编程真相
    一些鲜为人知的编程真相
    Ruby 1.9不会杀死Python
    Boost.Asio和ACE之间关于Socket编程的比较
    Effective C++第17条:要在单独的语句中使用智能指针来存储由new创建的对象
    Ruby 1.9不会杀死Python
    Boost智能指针——weak_ptr
    对象生死劫 - 构造函数和析构函数的异常
    Protocol Buffers:Google 的数据交换格式
    根据出生日期计算年龄
  • 原文地址:https://www.cnblogs.com/johnwonder/p/2324120.html
Copyright © 2011-2022 走看看