C#學習,反射

目錄

C#學習

.NET的體系結構

二次編譯

反射

什么是反射?

什么是Type?

什么是程序集?

反射API:

一,程序集

1, Load

2,LoadFrom

3,LoadFile

二,類型實例

1,無參構造

2,有參構造

3,私有構造

4,泛型類

三,方法調用

1,普通方法

2,靜態方法

3,私有方法

4,泛型方法

5,應用

四,屬性與字段

1,屬性讀寫

2,字段讀寫

3,應用

反射優缺點

優點

缺點

反射的價值是什么


C#學習

定義:面向對象,面向組件,類型安全,可以使用C#生成在.NET上運行的應用程序。

C#提供了語言構造來支持以上的定義,所以可以用來創建和使用軟件組件。

.NET的體系結構

C#在.NET上運行,.NET叫做,公共語言進行時(CLR)的虛擬執行系統和一組類庫.CLR 是 Microsoft 對公共語言基礎結構 (CLI) 國際標準的實現。 CLI 是創建執行和開發環境的基礎,語言和庫可以在其中無縫地協同工作。

用 C# 編寫的源代碼被編譯成符合 CLI 規范的中間語言 (IL)。 IL 代碼和資源(如位圖和字符串)存儲在擴展名通常為 .dll 的程序集中。 程序集包含一個介紹程序集的類型、版本和區域性的清單(metadata)。

執行 C# 程序時,程序集將加載到 CLR。 CLR 會直接執行實時編譯,將 IL 代碼轉換成本機指令。 CLR 可提供其他與自動垃圾回收、異常處理和資源管理相關的服務。

二次編譯

目的:一次編譯,多平臺使用,加一層中間層,更加靈活

由于系統很多,Mac,Win,Linux,其中Win還有32和64位的,為了做到一次編譯,多平臺運行,就需要二次編譯,C#源代碼被編譯成中間語言,存儲在擴展名通常為 .dll 的程序集中, 程序集包含一個介紹程序集的類型、版本和區域性的清單(metadata)。

這樣在不同的平臺,同一份編譯的中間語言,通過 CLR 轉換為不同平臺可執行機器指令,在不同平臺執行。

反射

什么是反射?

程序是用來處理數據的,但是程序本身也是由數據組成的,有關程序及其類型的數據,元數據(Metadata),保存在程序集之中,程序在運行中,可以查看其他的程序集和自身的Metadata,一個運行的程序查看本身的元數據或其他程序集的元數據的行為稱為反射。

什么是Type?

對于程序的類型,CLR都會創建一個包含這個類型的Type對象,程序中每遇到一個類型都會關聯到獨立的Type的對象,不管創建的類有多少實例,只有一個Type類的對象會關聯到這些所有的實例。

什么是程序集?

程序集是一個可以寄宿于 CLR 中的、擁有版本號的、自解釋、可配置的二進制文件,程序集的擴展名為 exe 或 dll。程序集是存放類型的集合,通過程序集可以獲取程序集內所有的類型信息

反射API:

一,程序集

如果沒有加載依賴,調用到使用依賴的對象時就會報錯。

1, Load

XXX:dll 名稱無后綴 從當前目錄加載 dll。開發環境 Bin ,發布程序是入口程序集文件當前目錄。

Assembly assembly = Assembly.Load("XXXX");
2,LoadFrom

XXX:已知程序集的文件名和路徑,會自動加載程序集的依賴程序集。

Assembly assembly = Assembly.LoadFrom("XXXX");
3,LoadFile

XXX:完整的dll路徑加載不會出錯,不會加載目標程序集所引用和依賴的其他程序集,需要自己控制并顯示加載所有依賴的程序集,如果沒有依賴項,使用的時候會錯。

Assembly assembly = Assembly.LoadFile("XXXX");

二,類型實例

1,無參構造

在獲取Assembly后獲取Type,根據Type創建實例,是Object類型的,為了編譯器可以通過需要進行類型轉換。

Type type = assembly.GetType("XXX.XXX");
object obj = (XXX)Activator.CreateInstance(type);
2,有參構造

在創建實例的時候,需要通過new object[]參數進行重載,此方法會根據 new object[] 里面的類型自動進行匹配構造函數

object obj = (XXX)Activator.CreateInstance(type, new object[] { "124", 123 });
3,私有構造

單例模式,在代碼里面為了避免外面進行實例化,在實現時都是以 private 修飾符對構造函數進行修飾,使其無法在外部進行實例化進行調用,但反射可以破壞這個規則。重點在 CreateInstance 方法,第二個參數 true

Assembly assembly = Assembly.LoadFrom("XXXX");
Type type = assembly.GetType("XXX.XXX");
object obj = Activator.CreateInstance(type,true);
4,泛型類

~n個占位符就代表幾個泛型,MakeGenericType 定義泛型類型,傳入 Type 數組即可

Assembly assembly = Assembly.LoadFrom("XXXX");
Type type = assembly.GetType("XXX~n");
Type typeNew = type.MakeGenericType(new Type[] { typeof(int), typeof(XXX),typeof(string)  });
object obj = Activator.CreateInstance(typeNew, new object[] { "124", 123 });

三,方法調用

1,普通方法
Assembly assembly = Assembly.Load("XXX");// dll
Type type = assembly.GetType("XXX");// 類型名稱
object instance = Activator.CreateInstance(type); // 根據 type 實例對象
MethodInfo method = type.GetMethod("XXX");// 方法名稱
method.Invoke(instance,new object[] { "方法參數1", "方法參數2" });
2,靜態方法

靜態成員,Invoke 無需傳入實例對象,因為靜態成員在類里面,只有一份,確定了 Type 后就已經有了其靜態成員。

Assembly assembly = Assembly.Load("XXX");// dll
Type type = assembly.GetType("XXX");// 類型名稱
MethodInfo method = type.GetMethod("XXX");// 方法名稱
method.Invoke(null,new object[] { "方法參數1", "方法參數2" });
3,私有方法

私有方法在面向對象編程語言是不可以被外部調用的,但反射可以破壞這個規則調用私有方法,重點在 GetMethod 方法第二個參數為 BindingFlags.Instance|BindingFlags.NonPublic。

Assembly assembly = Assembly.Load("XXX");// dll
Type type = assembly.GetType("XXX");// 類型名稱
object instance = Activator.CreateInstance(type); // 根據 type 實例對象
MethodInfo method = type.GetMethod("XXX",BindingFlags.Instance|BindingFlags.NonPublic);// 方法名稱
method.Invoke(instance, new object[] { "方法參數1", "方法參數2" });
4,泛型方法

無論是泛型類還是泛型方法,都需要通過 MakeGenericXXXX 方法指定泛型的類型,需要注意的是泛型類在加載類型時需要占位符,而泛型方法不需要。

Assembly assembly = Assembly.Load("XXX");// dll
Type type = assembly.GetType("XXX~2");// 類型名稱,~2 占位符,代表幾個泛型
Type typeNew = type.MakeGenericType(new Type[] { typeof(string), typeof(int) });
object instance = Activator.CreateInstance(typeNew); // 根據 type 實例對象
MethodInfo method = type.GetMethod("XXX");// 方法名稱
MethodInfo methodNew = method.MakeGenericMethod(new Type[] { typeof(int) });
methodNew.Invoke(instance, new object[] { "方法參數1", "方法參數2" });
5,應用

MVC就是使用的反射機制,在程序啟動時,會掃描 controller 類型的類,會將其 Type 緩存起來,當有請求過來時,就會到緩存中找到對于的 Type 反射進行實例化并調用其方法(也就是 action)。說到這 mvc 的 filter 也就是在 調用方法前后加點料(反射 invoke 方法前后)。

四,屬性與字段

1,屬性讀寫
Assembly assembly = Assembly.Load("XXX");// dll
Type type = assembly.GetType("XXX.XXX");// 類型名稱
object instance = Activator.CreateInstance(type); //實例對象
foreach (var prop in type.GetProperties())
{if (prop.Name.Equals("Id")){prop.SetValue(instance, 1);Console.WriteLine(prop.GetValue(instance));}else if (prop.Name.Equals("Name")){prop.SetValue(instance, "張三");Console.WriteLine(prop.GetValue(instance));}
}
2,字段讀寫
Assembly assembly = Assembly.Load("XXX");// dll
Type type = assembly.GetType("XXX.XXX");// 類型名稱
object instance = Activator.CreateInstance(type); //實例對象
foreach (var field in type.GetFields())
{if (field.Name.Equals("id")){field.SetValue(instance, 1);Console.WriteLine(field.GetValue(instance));}else if (field.Name.Equals("name")){field.SetValue(instance, "張三");Console.WriteLine(field.GetValue(instance));}
}
3,應用

有一個 entity 與 entityDto:

public class Product
{public int ID { get; set; }public String Name { get; set; }
}
public class ProductDto
{public int ID { get; set; }public String Name { get; set; }
}

然后對 entity 承載的數據進行了實例化,并且依次賦值個了 entityDto

Product product = new Product()
{ID = 1,Name = "張三"
};
?
ProductDto productDto = new ProductDto();
productDto.ID = product.ID;
productDto.Name = product.Name;

對于上面的情況,還算簡單,但是如果字段過多,手動賦值要花費的時間就大大增加,于是我們可以采用反射機制來提高效率,自動賦值,實際應用時,我們可以使用T來進行封裝:

Product product = new Product()
{ID = 1,Name = "張三"
};
Type productType = typeof(Product); // Product Type
Type productDtoType = typeof(ProductDto);// ProductDto Type
object productDto = Activator.CreateInstance(productDtoType); // ProductDto Instance
foreach (var prop in productDtoType.GetProperties())
{// 依次拿取 dto 屬性名稱,在 Product Type 查找,并且從 Product Instance 獲取值object val = productType.GetProperty(prop.Name).GetValue(product);// ProductDto Instance Set Propertie Valprop.SetValue(productDto,val);
}

反射優缺點

優點

動態:反射就兩個字動態,就像 MVC 就是將方法的調用動態化了。數據庫或者封裝的處理業務邏輯的算法等,可以使用配置文件進行動態切換使用。

缺點
  • coding 復雜:面向對象靜態編碼,一兩行的代碼反射得寫個四五行。

  • 避開編譯器檢查:平時寫代碼,我們寫錯了,編譯的時候會 error 提示我們,如果沒有編譯器寫得代碼不知道錯多少。但在反射里面,編譯器對類的操作不會進行檢查,這也是沒有辦法檢查,因為反射是動態的運行時的,不像普通編碼是靜態的。

反射的價值是什么

反射最直觀的區別是,由已有的固定類型,轉化為了字符串操作,且不需要在項目中進行引用(反射是動態的,依賴的是字符串)。因為依賴的是字符串,我們的程序才可配置化、才可易擴展,包括平時的框架開發都在大量使用反射(MVC、IOC、ORM等)。

學習參考自:菜鳥厚非

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

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

相關文章

SSM中接口+mapper文件(增刪改查)

IActivateInfoDao接口 public interface IActivateInfoDao{//根據用戶id和驗證類型,判斷認證是否已存在ActivateInfo selectByUserIdAndType(Param("userId") String userId, Param("type") String type);//插入int insert(ActivateInfo activ…

一文讀懂c++語言

一文讀懂C語言 C的發展C的設計目標C的特性C的挑戰 C的發展 C是一種通用的、高級的編程語言,它是C語言的擴展。C由Bjarne Stroustrup于1983年首次引入,并在之后的幾十年中不斷發展壯大。C被廣泛應用于各種領域,包括系統開發、游戲開發、嵌入式…

pytest數據驅動(最簡單)

目錄 第一種:通過yaml文件獲取數據(一維列表) 第二種:通過yaml文件獲取數據(二維列表) 第三種:通過yaml文件獲取數據(pytest.fixture) 資料獲取方法 第一種&#xff…

國際騰訊云賬號云核算概述!!

云核算概述 維基百科界說:云核算是一種依據互聯網的新型核算方法,經過互聯網上異構、自治的服務為個人和企業供給按需即取的核算。 云核算描繪的一起特征:云是一種按需運用的服務,運用者只重視服務本身。 云核算作為IT服務形式&am…

四、Linux中cd、pwd以及相對/絕對路徑和特殊路徑符

1、cd命令: cd命令可以切換當前工作目錄,基礎語法是: cd [linux路徑] (1)、打開Linux的命令提示行,當前工作目錄是home,輸入“cd /”,可以切換到根目錄下,在根目錄下輸…

6_AccessKeyId和AccessKeySecret的環境變量配置

系列文章目錄 第1章 Linux安裝Docker 第2章 Docker安裝jdk1.8和MySql 第3章 Docker安裝redis 第4章 Jar包部署Docker 第5章 Docker-compose多服務統一編排管理 第6章 AccessKeyId和AccessKeySecret的環境變量配置 文章目錄 系列文章目錄前言一、WIN系統配置二、LINUX系統配置三…

【go語言學習筆記】05 Go 語言實戰

文章目錄 一、 RESTful API 服務1. RESTful API 定義1.1 HTTP Method1.2 RESTful API 規范 2. RESTful API 風格示例3. RESTful JSON API4. Gin 框架4.1 導入 Gin 框架4.2 使用 Gin 框架4.2.1 獲取特定的用戶(GET)4.2.2 新增一個用戶(POST&am…

【前端 | CSS】align-items與align-content的區別

align-items 描述 CSS align-items 屬性將所有直接子節點上的 align-self 值設置為一個組。align-self 屬性設置項目在其包含塊中在交叉軸方向上的對齊方式 align-items是針對每一個子項起作用,它的基本單位是每一個子項,在所有情況下都有效果&…

SpringBoot復習:(31)Controller中返回的對象是如何轉換成json字符串給調用者的?

首先,SpringBoot自動裝配了HttpMessageConvertersAutoConfiguration這個自動配置類 而這個自動配置類又通過Import注解導入了JacksonHttpMessageConvertersConfiguration類, 在這個類中配置了一個類型為MappingJackson2HttpMessageConverter類型的bean…

vant van-tabs van-pull-refresh van-list 標簽欄+上拉加載+下拉刷新

<template><div class"huibj"><div class"listtab"><!--頂部導航--><div class"topdh"><topnav topname"余額明細"></topnav></div><!--Tab 標簽--><van-tabs v-model"…

Python教程(9)——Python變量類型列表list的用法介紹

列表操作 創建列表訪問列表更改列表元素增加列表元素修改列表元素刪除列表元素 刪除列表 在Python中&#xff0c;列表&#xff08;list&#xff09;是一種有序、可變的數據結構&#xff0c;用于存儲多個元素。列表可以包含不同類型的元素&#xff0c;包括整數、浮點數、字符串等…

配置 yum/dnf 置您的系統以使用默認存儲庫

題目 給系統配置默認存儲庫&#xff0c;要求如下&#xff1a; YUM 的 兩 個 存 儲 庫 的 地 址 分 別 是 &#xff1a; ftp://host.domain8.rhce.cc/dvd/BaseOS ftp://host.domain8.rhce.cc/dvd/AppStream vim /etc/yum.repos.d/redhat.repo [base] namebase baseurlftp:/…

C語言快速回顧(一)

前言 在Android音視頻開發中&#xff0c;網上知識點過于零碎&#xff0c;自學起來難度非常大&#xff0c;不過音視頻大牛Jhuster提出了《Android 音視頻從入門到提高 - 任務列表》&#xff0c;結合我自己的工作學習經歷&#xff0c;我準備寫一個音視頻系列blog。C/C是音視頻必…

Rabbitmq延遲消息

目錄 一、延遲消息1.基于死信實現延遲消息1.1 消息的TTL&#xff08;Time To Live&#xff09;1.2 死信交換機 Dead Letter Exchanges1.3 代碼實現 2.基于延遲插件實現延遲消息2.1 插件安裝2.2 代碼實現 3.基于延遲插件封裝消息 一、延遲消息 延遲消息有兩種實現方案&#xff…

2016年,進了百度

昨在深圳出差&#xff0c;與微信里的朋友吃了個便飯&#xff0c;他是今年四月份加的我微信&#xff08;gaoyang677&#xff09;&#xff0c;他的經歷很有意思&#xff0c;經他許可&#xff0c;分享給大家。 2012年時候&#xff0c;他大學畢業來到深圳&#xff0c;進了廠子&…

vue3 setup+Taro3 調用原生小程序自定義年月日時分多列選擇器,NutUI改造

vue3 setupTaro3 調用原生小程序自定義年月日時分多列選擇器&#xff0c;NutUI改造 NutUI 有日期時間選擇器&#xff0c;但是滑動效果太差&#xff0c;卡頓明顯。換成 原生小程序 很順暢 上代碼&#xff1a; <template><view><pickermode"multiSelector&…

2023牛客暑期多校訓練營9-J Puzzle: Star Battle

2023牛客暑期多校訓練營9-J Puzzle: Star Battle https://ac.nowcoder.com/acm/contest/57363/J 文章目錄 2023牛客暑期多校訓練營9-J Puzzle: Star Battle題意解題思路代碼 題意 解題思路 出題人都說是詐騙題&#xff08;&#xff0c;可以發現滿足每行每列恰好有 n n n個星…

python數據結構和算法

python數據結構和算法 參考 python圖解算法 選擇/快速排序 哈希表 廣度優先搜索算法 迪杰斯特拉算法 貪婪算法 動態規劃 K-鄰近算法 計算機科學是解決問題的研究。計算機科學使用抽象作為表示過程和數據的工具。抽象的數據類型允許程序員通過隱藏數據的細節來管理問題領域的…

【解決】Kafka Exception thrown when sending a message with key=‘null‘ 異常

問題原因&#xff1a; 如下圖&#xff0c;kafka 中配置的是監聽域名的方式&#xff0c;但程序里使用的是 ip:port 的連接方式。 解決辦法&#xff1a; kafka 中配置的是域名的方式&#xff0c;程序里也相應配置成 域名:port 的方式&#xff08;注意&#xff1a;本地h…

機器學習筆記之優化算法(十三)關于二次上界引理

機器學習筆記之優化算法——關于二次上界引理 引言回顧&#xff1a;利普希茲連續梯度下降法介紹 二次上界引理&#xff1a;介紹與作用二次上界與最優步長之間的關系二次上界引理證明過程 引言 本節將介紹二次上界的具體作用以及它的證明過程。 回顧&#xff1a; 利普希茲連續…