今天就說說。Net中通過反射取得某個類型時,我們怎麼知道這個類型在硬盤上的哪個角落?比如說,假如我們需要要求服務端動態載入某個數據源,那服務端怎麼知道數據源在哪?
網上大部分的教程都寫着,可以使用Assembly.Load方法來先加載程序集,然後再用Assembly.GetType或者Assembly.GetTypes方法處理。
這個方法很好很實用,基本上也就夠了。不過如果這麼無聊,也就算不上冷知識,更沒有必要寫這些了。
如果有辦法自動搜索程序集裏面有沒有暴露對應的類型,我們憑啥還要自行載入程序集?難道小又軟的那羣人也這麼無聊?其實還真是有辦法解決這個問題的。
Type.GetType,就是你了。
那麼,這個方法有什麼神奇的呢?Type.GetType有多個重載,其中除了一個沒有參數的以外,剩下的幾個重載要求至少一個字符串類型的typeName進行搜索,具體參見MSDN.比如下面這個例子:
using System;
namespace ConsoleApplication2
{
internal class Program
{
private static void Main(string[] args)
{
Type addedInRuntimeType = Type.GetType("LibA.TestClass, LibA, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null");
foreach (var propertyInfo in addedInRuntimeType.GetProperties())
{
Console.WriteLine(propertyInfo.Name);
}
}
}
}
假設目錄下我們有一個LibA.dll,LibA.dll裏面包含了一個類LibA.TestClass,以上代碼就能取得裏面的全部屬性名,接下來要對這個類型做什麼羞羞的事情那就各位看官自行決定咯。
但是,目前還是有一個限制沒有解決。GetType方法的參數中和文件有關的就只有typeName了。可是這貨並沒有指定路徑。如果要加載的類型所在的程序集在GAC中或者在當前程序集路徑下那還好,如果因爲各(xian)種(de)原(dan)因(teng)需要放到子目錄該怎麼辦呢?比如說要在子目錄"runtime"以及"runtme2"下進行搜索又該怎麼辦呢?還是直接放代碼
using System;
namespace ConsoleApplication2
{
internal class Program
{
private static void Main(string[] args)
{
AppDomain.CurrentDomain.AppendPrivatePath("runtime");
AppDomain.CurrentDomain.AppendPrivatePath("runtime2");
Type addedInRuntimeType = Type.GetType("LibA.TestClass, LibA, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null");
foreach (var propertyInfo in addedInRuntimeType.GetProperties())
{
Console.WriteLine(propertyInfo.Name);
}
}
}
}
AppDomain.CurrentDomain.AppendPrivatePath可以增加CLR搜索的路徑,不過這個方法已經被標記爲obsolete了。請自行無視這個警告吧。或者按如下代碼處理:
#pragma warning disable 618
AppDomain.CurrentDomain.AppendPrivatePath("runtime");
#pragma warning restore 618
繼續說點,其實這個路徑也可以寫在配置文件中的。MSDN說明在此,例子如下:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<probing privatePath="runtime;runtime2" />
</assemblyBinding>
</runtime>
</configuration>