C# 反射 (Reflect)

# C# 反射 (Reflect)

1.基本內容

我們可以使用反射動態地創建類型的實例,將類型綁定到現有對象,或從現有對象中獲取類型。然后,可以調用類型的方法或訪問其字段和屬性。

最基本的調用:

Assembly assembly = Assembly.Load("DB.SqlServer");//將加載dll 
Type type = assembly.GetType("DB.SqlServer.SqlServerHelper");//得到DLL 中的SqlServerHelper 類
object obj = Activator.CreateInstance(type);//創建類的實例
SqlServerHelper helper = (SqlServerHelper)obj;//將創建的Object 對象轉換為SqlServerHelper對象
helper.Query();//調用對象的方法

2.創建對象

工廠方法

反射的一個應用場景是,當我們開發的程序的數據庫是可能變化時,就會用到反射,入下述代碼:

//這是一個DB接口層
namespace DB.Interface
{public interface IDBHelper{void Query();}
}
//這是SqlServer數據庫的操作層
namespace DB.SqlServer
{public class SqlServerHelper : IDBHelper//繼承自DB接口層{public void Query(){Console.WriteLine("我是{0}", typeof(SqlServerHelper));}}
}
//這是MySql數據庫的操作層
namespace DB.MySql
{public class MySqlHelper : IDBHelper//繼承自DB接口層{public void Query(){Console.WriteLine("我是{0}", typeof(MySqlHelper));}}
}

然后我們會建造一個工廠類,專門用于生產對象:

//這是工廠層
public class Factory
{static string IDBHelperConfig = System.Configuration.ConfigurationManager.AppSettings["IDBHelperConfig"];static string DllName = IDBHelperConfig.Split(',')[0];static string TypeName = IDBHelperConfig.Split(',')[1];public static IDBHelper CreateDBHelper(){Assembly assembly = Assembly.Load(DllName);//將加載dll Type type = assembly.GetType(TypeName);//得到DLL 中的SqlServerHelper 類object obj = Activator.CreateInstance(type);//創建類的實例return (IDBHelper)obj;//將創建的Object 對象轉換為IDBHelper對象 并返回}
}

然后在app.config 文件中添加配置:

<appSettings><!--這是配置字符串--><add key="IDBHelperConfig" value="DB.SqlServer,DB.SqlServer.SqlServerHelper"/>
</appSettings>

最后在調用層面調用:

//這是調用
IDBHelper dbHelper = Factory.CreateDBHelper();
dbHelper.Query();

這樣當數據庫從SqlServer 修改為 MySql 時,我們只需要修改app.config中的配置字符串即可,而不需要修改源代碼,這樣有利于我們程序的維護,與穩定。

帶參數對象創建

基礎類

namespace Model
{public class Person{public int Id { get; set; }public string Name { get; set; }public DateTime CreateDate { get; set; }public Person(int id){Console.WriteLine("我是有1個參數的構造函數!");this.Id = id;}public Person(int id, string name){Console.WriteLine("我是有2個參數的構造函數!");this.Id = id;this.Name = name;}public Person(int id, string name, DateTime createDate){Console.WriteLine("我是有3個參數的構造函數!");this.Id = id;this.Name = name;this.CreateDate = createDate;}private Person(){Console.WriteLine("我是私有的,無參數構造函數");}}
}

有參數的構造函數調用方式:

Assembly assembly = Assembly.Load("Model");
Type personType = assembly.GetType("Model.Person");
//調用帶1個參數的構造函數
object obj = Activator.CreateInstance(personType, new object[] { 123 });
//調用帶2個參數的構造函數
object obj2 = Activator.CreateInstance(personType, new object[] { 123, "Oliver" });
//調用帶3個參數的構造函數
object obj3 = Activator.CreateInstance(personType, new object[] { 123, "Oliver", DateTime.Now });

調用私有構造函數

Assembly assembly = Assembly.Load("Model");
Type personType = assembly.GetType("Model.Person");
//調用私有函數
object obj4 = Activator.CreateInstance(personType,true);

泛型類創建

基礎類

namespace Model
{//添加泛型類public class GenericClass<T>{public GenericClass(){Console.WriteLine("我是泛型類的構造函數!");}public T GetT(){return default(T);}}
}

通過反射的方法創建泛型對象

Assembly assembly = Assembly.Load("Model");
Type gennericClassType = assembly.GetType("Model.GenericClass`1");//如果是一個泛型需要在后面添加`1,否則取出來的時NULL
Type newGennericClassType = gennericClassType.MakeGenericType(new Type[] { typeof(int) });
var obj = Activator.CreateInstance(newGennericClassType);

注意反射泛型類的時候GetType方法傳入的類名稱,需要在后面添加相應的泛型個數。下面這句代碼也相應的說明這個情況。

//輸出的值也會有一個`1
Console.WriteLine(typeof(GenericClass<int>));//輸出:Model.GenericClass`1[System.Int32]

3.調用方法

基礎類

namespace Model
{public class Person{public int Id { get; set; }public string Name { get; set; }public DateTime CreateDate { get; set; }public string Memo;//字段public Person(int id){Console.WriteLine("我是有1個參數的構造函數!");this.Id = id;}public Person(int id, string name){Console.WriteLine("我是有2個參數的構造函數!");this.Id = id;this.Name = name;}public Person(int id, string name, DateTime createDate){Console.WriteLine("我是有3個參數的構造函數!");this.Id = id;this.Name = name;this.CreateDate = createDate;}private Person(){Console.WriteLine("我是私有的,無參數構造函數");}//帶有返回值的無參方法public DateTime Show(){Console.WriteLine("我是帶有返回值的無參方法。");return DateTime.Now;}//帶有參數的方法public void Show2(int i){Console.WriteLine("我是Show2(int i).i=" + i);}//重載方法public void Show3(int i){Console.WriteLine("我是Show3(int i).i=" + i);}//重載方法public void Show3(string s){Console.WriteLine("我是Show3(string s).s=" + s);}//私有方法private void Show4(){Console.WriteLine("我是私有方法");}//靜態方法public static void Show5(){Console.WriteLine("我是靜態方法");}}
}

無參方法

Assembly assembly = Assembly.Load("Model");//加載dll
Type personType = assembly.GetType("Model.Person");//得到類
object objPerson = Activator.CreateInstance(personType, true);//創建對象
//調用 有返回值 無參數的方法
MethodInfo show = personType.GetMethod("Show");//找到方法
DateTime dt = (DateTime)(show.Invoke(objPerson, new object[] { }));//調用,并接收返回值

帶參數方法

//調用 帶有參數的方法
MethodInfo show2 = personType.GetMethod("Show2");
show2.Invoke(objPerson, new object[] { 123 });

重載方法

//調用 重載方法1
MethodInfo show3 = personType.GetMethod("Show3", new Type[] { typeof(int) });
show3.Invoke(objPerson, new object[] { 234 });//調用 重載方法2
MethodInfo show3_1 = personType.GetMethod("Show3", new Type[] { typeof(string) });
show3_1.Invoke(objPerson, new object[] { "ABC" });

私有方法

//調用私有方法
MethodInfo show4 = personType.GetMethod("Show4", BindingFlags.Instance | BindingFlags.NonPublic);
show4.Invoke(objPerson, new object[] { });

靜態方法(兩種形式)

//調用靜態方法
MethodInfo show5 = personType.GetMethod("Show5");
show5.Invoke(objPerson, new object[] { });//類似于 實例調用
show5.Invoke(null, new object[] { });//類似于直接通過類名稱調用

調用泛型類的泛型方法

基礎類

namespace Model
{//添加泛型類public class GenericClass<T>{public GenericClass(){Console.WriteLine("我是泛型類的構造函數!");}public T GetT<S>(T t, S s){Console.WriteLine("我是泛型類中的泛型方法!t_type:{0}, t_value:{1}\ts_type:{2}, s_value:{3}", typeof(T), t, typeof(S), s);return t;}}
}

調用GenericClass類的GetT方法

Assembly assembly = Assembly.Load("Model");
Type genericClassType = assembly.GetType("Model.GenericClass`1");//`1 千萬別忘記
Type newGenericClassType = genericClassType.MakeGenericType(new Type[] { typeof(int) });
object obj= Activator.CreateInstance(newGenericClassType);//創建對象
MethodInfo methodInfo = newGenericClassType.GetMethod("GetT");
MethodInfo newMethodInfo = methodInfo.MakeGenericMethod(new Type[] {  typeof(string) });
newMethodInfo.Invoke(obj, new object[] { 123, "Oliver" });//輸出:我是泛型類中的泛型方法!t_type:System.Int32, t_value:123       s_type:System.String, s_value:Oliver

4.get set 屬性、字段

屬性操作

Person p = new Person(1, "Oliver", DateTime.Now);
Type t = p.GetType();
PropertyInfo propertyInfo = t.GetProperty("Id");
Console.WriteLine(propertyInfo.GetValue(p));//獲取 屬性的值。輸出 1
propertyInfo.SetValue(p,123);//獲取 屬性的值
Console.WriteLine(propertyInfo.GetValue(p));//設置 屬性的值。輸出 123//遍歷屬性
foreach (var prop in t.GetProperties())
{Console.WriteLine("{0}.{1}={2}", typeof(Person), propertyInfo.Name, prop.GetValue(p));/*輸出:Model.Person.Id=123Model.Person.Id=OliverModel.Person.Id=2018/8/8 22:15:09*/
}

字段操作

Person p = new Person(1, "Oliver", DateTime.Now);
Type t = p.GetType();
FieldInfo fieldInfo = t.GetField("Memo");
Console.WriteLine(fieldInfo.GetValue(p));//獲取 屬性的值。輸出 空字符串
fieldInfo.SetValue(p, "自律給我自由");//獲取 屬性的值
Console.WriteLine(fieldInfo.GetValue(p));//設置 屬性的值。輸出 自律給我自由

轉載于:https://www.cnblogs.com/haowuji/p/9446118.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/451695.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/451695.shtml
英文地址,請注明出處:http://en.pswp.cn/news/451695.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

jsp中的%@ ...%

主要用來提供整個JSP 網頁相關的信息&#xff0c;并且用來設定JSP網頁的相關屬性

37--計算一個字符串中每個字符出現次數

1.問題描述 需求&#xff1a;計算一個字符串中每個字符出現次數。 2.解題思路 獲取一個字符串對象&#xff1b;創建一個Map集合&#xff0c;鍵代表字符&#xff0c;值代表次數&#xff1b;遍歷字符串得到每個字符&#xff1b;判斷Map中是否有該鍵&#xff1b;如果沒有&#…

oracle thin和oci 區別

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 Features of Oracle JDBC Drivers&#xff1a; 1.JDBC Oci 此驅動類似于傳統的ODBC 驅動。因為它需要Oracle Call Interface and Net8&…

從拿到班車手冊.xls到搜索附近班車地點

起因 七月份要去某廠報道了&#xff0c;異地租房的時候發現想租一個有公司班車的地方&#xff0c;卻不知道哪里有班車。輾轉流傳出班車手冊后發現搜索實在是太不方便了&#xff0c;于是有了一個主義&#xff0c;想做一個可以搜索房子地址&#xff0c;找出附近班車點&#xff08…

2018.08.09洛谷P3959 寶藏(隨機化貪心)

傳送門 回想起了自己賽場上亂搜的20分。 好吧現在也就是寫了一個隨機化貪心就水過去了&#xff0c;不得不說隨機化貪心大法好。 代碼&#xff1a; #include<bits/stdc.h> using namespace std; inline int read(){int ans0;char chgetchar();while(!isdigit(ch))chget…

AWT和Swing

AWT 是Abstract Window ToolKit (抽象窗口工具包)的縮寫&#xff0c;這個工具包提供了一套與本地圖形界面進行交互的接口。AWT 中的圖形函數與操作系統所提供的圖形函數之間有著一一對應的關系&#xff0c;我們把它稱為peers。 也就是說&#xff0c;當我們利用 AWT 來構件圖形用…

解決 : Apache Tomcat/8.0.0-RC1 - Error report ... HTTP Status 404

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 1.報錯&#xff1a; Apache Tomcat/8.0.0-RC1 - Error report HTTP Status 404 - /richer/getOnLineRicherCount The requested resour…

py 5.24

#面向對象 #類&#xff1a;模子。Person&#xff0c;不具體。 #實例/對象&#xff1a;依托于類產生的具體的帶有屬性的。alex #實例化&#xff1a;產生對象的過程。 alex Person() #類&#xff1a; #分為靜態屬性&#xff08;一般的變量&#xff09;。動態屬性(函數&#xff0…

多線程原理實例應用詳解

從單進程單線程到多進程多線程是操作系統發展的一種必然趨勢&#xff0c;當年的DOS系統屬于單任務操作系統&#xff0c;最優秀的程序員也只能通過駐留內存的方式實現所謂的"多任務"&#xff0c;而如今的Win32操作系統卻可以一邊聽音樂&#xff0c;一邊編程&#xff0…

git中使用fork

在git中使用fork相當于你在原項目的主分支上又建立了一個分支&#xff0c;你可以在該分支上任意修改。如果想將你的修改合并到原項目中時&#xff0c;可以pull request&#xff0c;這樣原項目的作者如果認同你的修改&#xff0c;就可以將你修改的東西合并到原項目的主分支上去。…

一、【Collection、泛型】

主要內容 Collection集合迭代器增強for泛型 教學目標 能夠說出集合與數組的區別 說出Collection集合的常用功能 能夠使用迭代器對集合進行取元素 能夠說出集合的使用細節 能夠使用集合存儲自定義類型 能夠使用foreach循環遍歷集合 能夠使用泛型定義集合對象 能夠理解泛型上下…

字符裝換

2019獨角獸企業重金招聘Python工程師標準>>> 字母大小寫轉換 a →A char toUpperCase( char ch){ if((ch >a) && (ch <z)){ return (char)(ch - 32); // 主要 這里(char)是必要的&#xff0c;因為char -32是返回的數值&#xff0c;必須轉換成對應的字…

解決 Unable to translate SQLException with Error code ‘17059‘, will now try the fallback translator

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 1.報錯&#xff1a; Unable to translate SQLException with Error code 17059, will now try the fallback translator 報錯如下&…

企業使用開源軟件的風險

很多時候&#xff0c;我們過高地估計了開源軟件面臨的版權威脅&#xff0c;開源軟件并非天生就比專有軟件存在更多風險。雖然在企業中開源軟件越來越普及&#xff0c;但開源軟件始終難以擺脫知識產權帶來的陰影。2007年&#xff0c;微軟聲稱開源軟件侵犯了它235項專利&#xff…

杭電多校 Harvest of Apples 莫隊

問題 B: Harvest of Apples 時間限制: 1 Sec 內存限制: 128 MB 提交: 78 解決: 35 [提交] [狀態] [討論版] [命題人:admin] 題目描述 There are n apples on a tree, numbered from 1 to n. Count the number of ways to pick at most m apples. 輸入 The first line of the …

linux和GNU之間的關系

Linux只是一個操作系統內核而已&#xff0c;而GNU提供了大量的自由軟件來豐富在其之上各種應用程序。 因此&#xff0c;嚴格來講&#xff0c;Linux這個詞本身只表示Linux內核&#xff0c;但在實際上人們已經習慣了用Linux來形容整個基于Linux內核&#xff0c;并且使用GNU 工程各…

二、【List、Set、數據結構、Collections】

主要內容 數據結構List集合Set集合Collections 教學目標 能夠說出List集合特點 能夠說出常見的數據結構 能夠說出數組結構特點 能夠說出棧結構特點 能夠說出隊列結構特點 能夠說出單向鏈表結構特點 能夠說出Set集合的特點 能夠說出哈希表的特點 使用HashSet集合存儲自定義元素…

@Java | Thread synchronized - [ 線程同步鎖 基本使用]

對實現了Runnable或者Callable接口類&#xff0c;可以通過多線程執行同一實例的run或call方法&#xff0c;那么對于同一實例中的局部變量&#xff08;非方法變量&#xff09;就會有多個線程進行更改或讀取&#xff0c;這就會導致數據不一致&#xff0c;synchronized(關鍵字)可以…

解決bad SQL grammar []; nested exception is java.sql.SQLSyntaxErrorException: ORA-00911: 無效字符

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 1. 報錯&#xff1a; ### Cause: java.sql.SQLSyntaxErrorException: ORA-00911: 無效字符; bad SQL grammar []; nested exception is …

開源代碼的使用 二次開發

開源開發&#xff0c;就我的理解&#xff0c;有三種。 1、當作底層基礎&#xff0c;使用。例如大家使用mysql就算。有人會認為我說錯了。但我認為&#xff0c;開發不代表就是要同一個語言&#xff0c;甚至修改代碼。例如我們使用動態庫&#xff0c;原先的動態庫是什么寫的并不重…