关于跨程序集的反射

    在开发中,经常会遇到这种情况,在A.dll中需要反射B.dll中的类型,如果稍不注意,就会产生运行时错误。关于跨程序集的反射,记住两点就可以:
(1)如果使用typeof,编译能通过,则跨程序集的反射一定可以正常运行。可以说,typeof是支持强类型的。比如
Type supType = typeof(EnterpriseServerBase.DataAccess.IDBAccesser) ;
    如果当前程序集没有添加对EnterpriseServerBase.dll的引用,则编译会报错。

(2)如果使用Type.GetType,情况就复杂些,这是因为Type.GetType是非强类型的。Type.GetType的参数是一个string,当string表示的目标类型不在当前程序集中,则运行时Type.GetType会返回null。解决的办法是:首先加载目标程序集,然后再使用Assembly.GetType方法。如
            Assembly asmb = Assembly.LoadFrom("EnterpriseServerBase.dll") ;
            Type supType 
= asmb.GetType("EnterpriseServerBase.DataAccess.IDBAccesser") ;
    注意,当使用Type.GetType的时候,即使你添加了对EnterpriseServerBase.dll的引用,Type.GetType("EnterpriseServerBase.DataAccess.IDBAccesser")也会返回null,这是因为Type.GetType只会在当前程序集中进行类型搜索!

    以前曾写过一篇“关于跨程序集的反射”的blog,关于跨程序集加载类型,文中使用的是方法是:先加载目标类型所在的程序集,再使用Assembly. GetType方法获取类型。文后Luna兄的评论说,可以直接使用Type.GetType("<<完全限定类名>>,<<程序集>>")来加载类型,当初我查了MSDN,MSDN中也说到了这一点,我也就记住了这个解决方案。但是,今天使用这种方式来跨程序集进行类型加载时,却始终返回null。难道MSDN有误?我不知道。(还望知道的仁兄告知,呵呵)。

    在Spring.net中,配置文件中,通常出现类似下面的配置项:
<object name="dataStreamHelper" type="DataCenterBase.Common.DataStreamHelper ,DataCenterBase"/>
    配置中的“type”的值正好与Type.GetType方法的参数格式完全一致,于是我猜想Spring.net是使用了Type.GetType方法。我查看了Spring.net这块的源代码,出乎意料的是Spring.net并没有使用Type.GetType这个捷径,而仍然使用了Assembly.GetType方法。也不知道为什么,呵呵

    为了以后使用方便,我自己封装了一个静态方法,来支持任意类型的加载。
 1         #region GetType
 2         // assemblyName 不用带扩展名 ,如果目标类型在当前程序集中,assemblyName传入null    
 3         public static Type GetType(string typeFullName ,string assemblyName)
 4         {
 5             if(assemblyName == null)
 6             {
 7                 return Type.GetType(typeFullName) ;
 8             }
 9 
10             //搜索当前域中已加载的程序集
11             Assembly[] asses = AppDomain.CurrentDomain.GetAssemblies();
12             foreach (Assembly ass in asses)
13             {
14                 string[] names = ass.FullName.Split(',') ;
15                 if(names[0].Trim() == assemblyName.Trim())
16                 {
17                     return ass.GetType(typeFullName) ;
18                 }
19             }
20 
21             //加载目标程序集
22             Assembly tarAssem = Assembly.LoadWithPartialName(assemblyName) ;
23             if(tarAssem != null)
24             {
25                 return tarAssem.GetType(typeFullName) ;
26             }
27 
28             return null ;
29         }
30         #endregion

    关于使用Type.GetType加载非当前程序集中的类型,谁有成功的经验了?感谢分享下。
posted @ 2006-01-20 20:47  torome  阅读(520)  评论(0编辑  收藏  举报