背景
我們考慮一下這樣的一個場景我們需要開發了一個用於排序的通用的可擴展的庫利用該庫用戶可以自定義排序規則(比較大小)以及需要進行排序的數據類型而同時我們開發了一個應用程序在該應用程序中我們可以讓用戶選擇排序算法來進行排序由於我們的排序庫是可擴展的因此在開發應用程序的時候我們並不知道會有多少種排序算法可供使用因此我需要通過讀取配置文件來動態的加載排序算法
排序庫SortLib
在SortLib中我們定義所有排序算法的通用接口ISortAlgorithm
public interface ISortAlgorithm<T>
{
void Sort(List<T> source Func<T T int> compare);
}
比如我們有一個排序算法叫HeapSort注意該算法可能在SortLib程序集中也可能不在
public class HeapSortAlgorithm<T> : ISortAlgorithm<T>
{
public void Sort(List<T> source Func<T T int> compare)
{
//TODO: sort the source
}
}
應用程序SortApp
動態創建排序算法
我們知道要動態的創建HeapSortAlgorithm只需要獲取到其類型然後利用ActivatorCreateInstance就行例如:
ActivatorCreateInstance(AssemblyLoad(assembly)GetType(full type name);
而在此處由於我們的HeapSortAlgorithm是個泛型類則需要給泛型中的T賦予實際的類型我們可以通過先獲取泛型類型再通過MakeGenericType來創建實際的類型如下
string assemblyName = stringEmpty;
string fullTypeName = stringEmpty;
//TODO: 讀取配置文件賦值給assemblyName和fullTypeName
Type[] typeArgs = { typeof(int) };
Type algTypeGen = AssemblyLoad(assemblyName)GetType(fullTypeName);
//TODO: 判斷algTypeGen是否實現了ISortAlgorithm<T>接口
// 獲取HeapSortAlgorithm<int>類型
Type algType = algTypeGenMakeGenericType(typeArgs);
HeapSortAlgorithm<int> heapSortAlg = ActivatorCreateInstance(algType);
如此這般我們的HeapSort算法就可以用上
配置文件
為了使我們的應用程序能夠用上HeapSort我們將其添加到我們的配置文件中去如下
<SortAlgorithms>
<Algorithm name=HeapSort assembly=SortLib type=SortLibHeapSortAlgorithm` />
</SortAlgorithms>
注意到配置中type一項設置為SortLibHeapSortAlgorithm`這是因為泛型類HeapSortAlgorithm<T>在運行過程中它的實際名稱是HeapSortAlgorithm`這也可以通過typeof(HeapSortAlgorithm<>)得到(注關於這點不知道這個泛型的名稱會不會變成HeapSortAlgorithm`之類的筆者還不太確定希望有哪個大大們賜教)
另如何去讀取配置文件的代碼在本文中我就不貼出來了可以自己寫ConfigurationSection類後來獲取(推薦)或者直接通過c#中讀取XML文件的方式來實現:)
判斷類型是否實現泛型接口
判斷algTypeGen是否實現了ISortAlgorithm<T>接口可以通過對algTypeGen實現的所有接口與ISortAlgorithm<>循環比對即可實現
Type baseSortAlgType = typeof(ISortAlgorithm<>);
bool isImplemented = algTypeGenGetInterfaces()Any(x =>
xIsGenericType &&
xGetGenericTypeDefinition() == baseSortAlgType);
後記
在本文中我們了解了如何通過配置實現動態創建泛型類型的實例希望對大家有所幫助
From:http://tw.wingwit.com/Article/program/net/201311/13694.html