反射的實現原理
了解反射的原理先了解.net編譯過程(參照.net編譯過程筆記),c#高階語言經過編譯器的編譯之後生成了dll或exe,該dll或exe的組成有兩部分metadata和il,il經過jit進一步編譯為機器語言,這裡就有乙個metadata,該metadata就是用來描述dll或exe的,而反射就是通過獲取metadata的資訊來訪問程式集中的資訊,實現常用的建立型別,呼叫方法等操作。
反射入口之一 (assembly)
作用assembly用來載入dll,獲取dll中的資訊。
方法
assembly assembly;
assembly = assembly.load("reflectiondemo"); //程式集的名稱,不帶檔案型別,從當前執行目錄載入,需要新增引用,或者複製到當前執行目錄
//assembly = assembly.loadfile(@"d:\cgbbank\wpflibrary\baselibrary\reflectiondemo\bin\debug\reflectiondemo.dll");
//assembly = assembly.loadfrom("reflectiondemo.dll"); //程式集的檔名或路徑
常用方法//載入dll
assembly assembly = assembly.load("reflectiondemo");
//獲取型別名稱,引數為完整名稱:命名空間+類名稱
type type = assembly.gettype("reflectiondemo.mysqlhelp");
//建立物件
object objhelp = activator.createinstance(type);
//呼叫方法
mysqlhelp mysqlhelp = (mysqlhelp)objhelp;
mysqlhelp.query();
mysqlhelp mysqlhelp = new mysqlhelp();
mysqlhelp.query();
注意:如果是createhelp中靜態字段獲取失敗,則無法進入該函式,也無法除錯,比如,createhelp函式中的靜態欄位在讀取配置檔案時出錯,可能是配置檔案格式錯誤導致的等
反射呼叫私有方法,破壞單例模式
單列模式保證了在執行環境中只有乙個例項被建立,在同的位置使用的都是相同的例項,單例模式實現如下:
/// /// 單例模式
///
public class singleton
//靜態建構函式建立例項,只在程式執行時建立一次
static singleton()
//給外部提供乙個獲取例項的方法
public static singleton createinstance()
}
那麼外部程式需要建立以上類的例項就只能通過呼叫createinstance()方法,而該方法總是返回乙個靜態唯一的例項,從而實現單例模式。
但是使用反射就可以呼叫類私有的建構函式建立物件,從而破壞單例模式。反射呼叫如下:
assembly assembly = assembly.load("baselibrary");
type type = assembly.gettype("baselibrary.basedemo.reflection.singleton");
object objsingle = activator.createinstance(type, true); //第二個引數true指定可以呼叫預設的建構函式
建立不同建構函式的例項
使用反射建立例項是呼叫了預設的建構函式,當然可以通過指定引數來呼叫指定的建構函式,建立方法如下:
assembly assembly = assembly.load("baselibrary");
type type = assembly.gettype("baselibrary.basedemo.reflection.mutitest");
object objtest1 = activator.createinstance(type, new object); //呼叫接受乙個整型型別的建構函式
object objtest2 = activator.createinstance(type, new object );//呼叫接受乙個strin型別的建構函式
createinstance(),函式接受第二個引數為乙個物件陣列,陣列中為建構函式的引數,通過傳入不同的個數和不同型別的引數來匹配不同的建構函式。
反射入口之二 (type)
system.type類可以訪問任何資料型別的資訊,如以下方式訪問乙個類的資訊:
student stu = new student ;
type typestu = typeof(student);
//等同於
type typestu = stu.gettype();
常用屬性//獲取所有的屬性
propertyinfo propertyinfo = typestu.getproperties();
//獲取指定的屬性
propertyinfo proper = typestu.getproperty("myproterty");
//獲取私有屬性
propertyinfo = typestu.getproperties(bindingflags.instance | bindingflags.nonpublic);
//獲取字段
fieldinfo fieldinfo = typestu.getfields();
methodinfo methodinfo_1 = typestu.getmethods(bindingflags.instance | bindingflags.public | bindingflags.createinstance);
//建立例項,呼叫方法,usetypeinvoke為public class usetypeinvoke{};
type type = typeof(usetypeinvoke);
object objinstance = activator.createinstance(type);
usetypeinvoke usetypeinvoke = (usetypeinvoke)objinstance;
usetypeinvoke.init1(); //呼叫方式一
methodinfo method_1 = type.getmethod("init1");
method_1.invoke(objinstance,null); //呼叫方法方式二,使用invoke無法呼叫過載類函式
dynamic dyninstance = activator.createinstance(type);
dyninstance.init1(); //呼叫方式三,使用dynamic,呼叫方式時需要保證該方法必須存在否則會報錯
//呼叫帶有引數的方法
methodinfo method_2 = type.getmethod("init2");
object objinstance_2 = activator.createinstance(type);
method_2.invoke(objinstance_2, new object ); //呼叫帶有引數
//呼叫靜態方法
methodinfo method_3 = type.getmethod("init3");
object objinstancd_3 = activator.createinstance(type);
method_3.invoke(objinstancd_3,new object);
//或者,靜態方法可以不用傳遞例項物件
method_3.invoke(null,new object);
23 Java入門 反射之方法反射的基本操作
方法的反射 1.獲取a類中的print int,int 方法 要獲取乙個方法就是獲取類的資訊,獲取類的資訊首先要獲取類的類型別 a a1 new a class c a1.getclass 獲取方法 由名稱和引數列表來決定,getmethod獲取的是public方法,getdelcaredmetho...
一正規化 二正規化 三正規化
1 第一正規化 如果乙個關係模式r的所有屬性都是不可分的基本資料項,則r 1nf。簡單的說,第一正規化就是每乙個屬性都不可再分。不符合第一正規化則不能稱為關聯式資料庫。第一正規化 1nf 要求資料庫表的每一列都是不可分割的基本資料項,同一列中不能有多個值。若某一列有多個值,可以將該列單獨拆分成乙個實...
基本網路程式設計正規化
本文是自己學習經驗總結,有不正確的地方,請批評指正。關於程序和執行緒的網路程式設計模型,在unp卷1的第30章,有詳細的介紹。我這裡,在tiny基礎上,實現了以下幾種 其中,fdbuffer是指主線程accept得到已連線描述符後,存放進fdbuffer緩衝區,其他執行緒再去處理。signal si...