原由 :
十年前前寫結構矩陣或是Finite Element Method時,都是依照element的不同性質,代入一個相同的位移分析主程式。因此只要能將element代入主程式,就能夠在不動到主程式的情況下,動態增加element種類,也就是Reflection。問題就在於C++並沒有真正的late binding,到Smalltalk及後來的Java、.Net出現後才真正有此能力。若勉強用C++要寫,得用到function pointer之類的技巧,就又成為weak type。
以下是C的switch case範例,取自Alladin
就算是使用Abstract Factory,仍然是省不了這一大串的select case,更別說source不給對方了。
最近寫另一個C#程式,剛好想起來這個問題,就可以用Registry加上Reflection。
利用唯一的一個Singleton Registry利用Reflection找出所有可用的類別,放到collection裏;而在系統動態載入某一類別(.class、.jar或是.dll)後,又可以再增加類別。
簡言之,Registry是利用Reflection加上Singleton及Iterator 3種pattern寫成的。
範例如下:
Element是我訂的Interface,裏頭有一個Abstract Method: Register
十年前前寫結構矩陣或是Finite Element Method時,都是依照element的不同性質,代入一個相同的位移分析主程式。因此只要能將element代入主程式,就能夠在不動到主程式的情況下,動態增加element種類,也就是Reflection。問題就在於C++並沒有真正的late binding,到Smalltalk及後來的Java、.Net出現後才真正有此能力。若勉強用C++要寫,得用到function pointer之類的技巧,就又成為weak type。
以下是C的switch case範例,取自Alladin
ARRAY *elmt_cst ( ARRAY *p, int isw ) {
/* [a] : Jump to Task Case */
UNITS_SWITCH = CheckUnits();
switch(isw) {
case PROPTY: /* CST material properties */
..... add details of CST material properties ....
break;
case LOAD_MATRIX: /* compute equivalent nodal loads */
case STRESS: /* compute internal nodal loads */
..... fill in details here ....
break;
case STIFF: /* compute element-level stiffness matrix */
..... put details of element stiffness matrix here ....
break;
case MASS_MATRIX: /* compute element-level mass matrix */
..... put details of element mass matrix here ....
break;
default:
break;
}
就算是使用Abstract Factory,仍然是省不了這一大串的select case,更別說source不給對方了。
最近寫另一個C#程式,剛好想起來這個問題,就可以用Registry加上Reflection。
利用唯一的一個Singleton Registry利用Reflection找出所有可用的類別,放到collection裏;而在系統動態載入某一類別(.class、.jar或是.dll)後,又可以再增加類別。
簡言之,Registry是利用Reflection加上Singleton及Iterator 3種pattern寫成的。
範例如下:
Element是我訂的Interface,裏頭有一個Abstract Method: Register
///
/// 介面 Element,定義方法Register
///
interface Element
{
public void Register();
}
///
/// 利用Reflection註冊所有Element的子類別
///
private static void RegisterSubClasses()
{
Assembly a = typeof (SingletonInstrumentRegistry).Module.Assembly;
Module[] modules = a.GetModules();
for (int i = 0; i < modules.Length; i++)
{
Type[] types = modules[i].GetTypes();
for (int j = 0; j < types.Length; j++)
{
if ((!types[j].IsAbstract) && types[j].IsSubclassOf(typeof (Element)))
{
// 產生子類別的 instance
Object obj = types[j].InvokeMember(null,
BindingFlags.DeclaredOnly |
BindingFlags.Public |
BindingFlags.Instance |
BindingFlags.CreateInstance,
null, null, null);
types[j].InvokeMember("Register",
BindingFlags.DeclaredOnly |
BindingFlags.Public | BindingFlags.NonPublic |
BindingFlags.Instance | BindingFlags.InvokeMethod,
null, obj, null);
}
}
}
}
如果類別的方法又是Singleton,就可以做成非常方便又省記憶體的一種方式。但是,經實測後Reflection很慢,若類別太多,可以考慮做成查表法,將類別名稱儲存於xml檔案。
留言