反射(一)之 基本正規化

2021-09-28 19:47:10 字數 4033 閱讀 8021

反射的實現原理

了解反射的原理先了解.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...