.NET Emit 入門教程:第六部分:IL 指令:5:詳解 ILGenerator 指令方法:創建實例指令

来源:https://www.cnblogs.com/cyq1162/p/18112967
-Advertisement-
Play Games

在.NET Emit 入門教程的第六部分中,我們深入探討了 ILGenerator 指令方法,特別是關於創建實例指令的詳細解釋。ILGenerator 是.NET框架中的一個強大工具,用於在運行時生成和執行IL代碼。在這篇文章中,我們學習瞭如何使用 ILGenerator 來創建實例,其中主要涉及到... ...


前言:

上上篇介紹了 IL 指令的分類以及參數載入指令,該載入指令以 Ld 開頭,將參數載入到棧中,以便於後續執行操作命令。

上一篇介紹參數存儲指令,其指令以 St 開頭,將棧中的數據,存儲到指定的變數中,以方便後續使用。

本篇將介紹創建實例指令,其指令以 New 開頭,用於在運行時動態生成並初始化對象。

創建實例指令簡介

在.NET Emit 中,使用 ILGenerator 創建實例是一項重要的操作,它允許我們動態生成對象實例和數組實例的代碼。

通過創建實例指令,我們可以在運行時動態生成並初始化對象,為程式提供更大的靈活性和可擴展性。

創建實例指令主要包括 Newobj 指令和 Newarr 指令。

Newobj 指令用於創建新的對象實例,而 Newarr 指令則用於創建新的數組實例。

這些指令的靈活運用可以幫助我們在運行時動態地生成各種類型的實例,滿足不同場景下的需求。

在本篇文章中,我們將深入探討 ILGenerator 中的創建實例指令,詳細解析其用法和示例代碼。

通過學習本文內容,讀者將能夠掌握如何利用 ILGenerator 創建對象實例和數組實例,從而更好地理解和應用.NET Emit 技術。

1、創建實例指令:Newobj

對於該指令,其核心在於如何獲取構造函數並作為參數傳遞,下麵看一組示例。

共用代碼,定義實體(包含無參構造函數、有參構造函數、基本變數):

 public class Entity
 {
     public Entity()
     {

     }
     public Entity(int id)
     {
         this.ID = id;
     }
     public int ID;
 }

共用代碼,生成程式集,以方便後續對照參考:

AssemblyName assName = new AssemblyName("myAssembly") { Version = new Version("1.1.1.2") };
AssemblyBuilder ab = AppDomain.CurrentDomain.DefineDynamicAssembly(assName, AssemblyBuilderAccess.RunAndSave);
ModuleBuilder mb = ab.DefineDynamicModule("myModule", "b.dll");
TypeBuilder tb = mb.DefineType("MyNameSpace.MyClass", TypeAttributes.Public | TypeAttributes.Class);

//定義靜態方法
MethodBuilder methodBuilder = tb.DefineMethod("NewObj", MethodAttributes.Public | MethodAttributes.Static, typeof(Entity), new Type[] { });
ILGenerator il = methodBuilder.GetILGenerator();

//il 代碼處......


Type classType = tb.CreateType();

ab.Save("b.dll");

A、無參數實例化:通過 Type 的 GetConstructor 實例方法獲取類型的構造函數。

ILGenerator il = methodBuilder.GetILGenerator();
il.Emit(OpCodes.Newobj, typeof(Entity).GetConstructor(Type.EmptyTypes));
il.Emit(OpCodes.Ret);     // 返回該值

對照生成:

B、使用參數實例化:

 ILGenerator il = methodBuilder.GetILGenerator();
 il.Emit(OpCodes.Ldc_I4, 999);
 il.Emit(OpCodes.Newobj, typeof(Entity).GetConstructor(BindingFlags.Public | BindingFlags.Instance, null, new Type[] { typeof(int) }, null));
 il.Emit(OpCodes.Ret);     // 返回該值

對照生成:

小說明:

這裡構造函數的參數傳入,是通過 Ld 系列指令按順序壓入棧中。

2、創建實例指令:Newarr

該指令用於創建數組對象,該指令需要指定數組長度。

A、創建數組:

ILGenerator il = methodBuilder.GetILGenerator();
il.Emit(OpCodes.Ldc_I4, 6);
il.Emit(OpCodes.Newarr, typeof(Entity));
il.Emit(OpCodes.Ret);     // 返回該值

對照生成代碼:

小說明:

Newarr 接收的參數,是 Type 類型。

Newobj 接收的參數,是 ConstructorInfo 構造函數類型。

B、對數組賦值:引用類型

ILGenerator il = methodBuilder.GetILGenerator();

//創建數組
il.Emit(OpCodes.Ldc_I4, 3);
il.Emit(OpCodes.Newarr, typeof(Entity));

il.DeclareLocal(typeof(Entity[]));
il.DeclareLocal(typeof(Entity));
il.Emit(OpCodes.Stloc_0);//存儲數組

for (int i = 0; i < 3; i++)
{
    il.Emit(OpCodes.Newobj, typeof(Entity).GetConstructor(Type.EmptyTypes));//定義實體類
    il.Emit(OpCodes.Stloc_1);//存儲實體類

    il.Emit(OpCodes.Ldloc_0);//載入數組
    il.Emit(OpCodes.Ldc_I4, i);//載入索引
    il.Emit(OpCodes.Ldloc_1);//載入Entity

    il.Emit(OpCodes.Stelem_Ref);//引用類型賦值
}


il.Emit(OpCodes.Ldloc_0);//載入數組
il.Emit(OpCodes.Ret);     // 返回該值

對照生成代碼:

C、對數組賦值:值類型

ILGenerator il = methodBuilder.GetILGenerator();

//創建數組
il.Emit(OpCodes.Ldc_I4, 3);
il.Emit(OpCodes.Newarr, typeof(DateTime));

il.DeclareLocal(typeof(DateTime[]));
il.DeclareLocal(typeof(DateTime));
il.Emit(OpCodes.Stloc_0);

for (int i = 0; i < 3; i++)
{// 調用 DateTime.Parse 方法創建 DateTime 實例
    MethodInfo parseMethod = typeof(DateTime).GetMethod("Parse", new Type[] { typeof(string) });
    il.Emit(OpCodes.Ldstr, DateTime.Now.ToString()); // 傳遞當前時間字元串
    il.Emit(OpCodes.Call, parseMethod);    // 調用 Parse 方法
    il.Emit(OpCodes.Stloc_1);

    il.Emit(OpCodes.Ldloc_0);//載入數組
    il.Emit(OpCodes.Ldc_I4, i);//載入索引
    il.Emit(OpCodes.Ldloc_1);//載入Entity


    il.Emit(OpCodes.Stelem, typeof(DateTime));//賦值
}

il.Emit(OpCodes.Ldloc_0);
il.Emit(OpCodes.Ret);     // 返回該值

對照生成代碼:

D、數組取值指令:

總結:

在.NET Emit 入門教程的第六部分中,我們深入探討了 ILGenerator 指令方法,特別是關於創建實例指令的詳細解釋。

ILGenerator 是.NET框架中的一個強大工具,用於在運行時生成和執行IL代碼。

在這篇文章中,我們學習瞭如何使用 ILGenerator 來創建實例,其中主要涉及到了兩種指令方法:newobj 和 newarr。

通過 newobj 指令,我們可以在IL代碼中調用構造函數來創建類的實例,而 newarr 指令則用於創建數組實例。

通過學習這些內容,讀者可以更深入地理解 ILGenerator 的使用,併在實際項目中應用動態代碼生成的技術。

下一篇,我們將學習方法調用指令的相關內容。

版權聲明:本文原創發表於 博客園,作者為 路過秋天 本文歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則視為侵權。
個人微信公眾號
Donation(掃碼支持作者):支付寶:
Donation(掃碼支持作者):微信:

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • C++ 20 的 std::format 是一個很神奇、很實用的工具,最神奇的地方在於它能在編譯期檢查字元串的格式是否正確,而且不需要什麼特殊的使用方法,只需要像使用普通函數那樣傳參即可。 #include <format> int a = 1; std::string s1 = std::form ...
  • 官網:Vue Router | Vue.js 的官方路由 (vuejs.org) 安裝命令:npm install vue-router@4 1.添加兩個頁面\vuedemo\src\views\index.vue、\vuedemo\src\views\content.vue 2.添加\vuedem ...
  • 首先插件添加:Live Server、Vue - Official、Vue VSCode Snippets、別名路徑跳轉 官網:Vite | 下一代的前端工具鏈 (vitejs.dev) 1.創建一個文件夾VueApp,運行cmd轉到該目錄下,執行命令:npm create vite@latest ...
  • 1.安裝node.js : Node.js — Run JavaScript Everywhere (nodejs.org) 2.查看安裝版本命令:node -v 、 npm -v, npm是Node.js包管理器, 用來安裝各種庫、框架和工具。 3.查看當前的鏡像源: npm get regist ...
  • 在Avalonia的UI框架中,TemplatedControl是一個核心組件,它提供了一種強大的方式來創建可重用且高度可定製的控制項。 本文將深入探討TemplatedControl的概念、其帶來的優勢以及它在實際開發中的應用場景,並通過一個示例代碼來展示其用法。 什麼是TemplatedContr ...
  • 本文探討了.NET Emit 入門教程的第六部分,聚焦於ILGenerator中的方法調用指令。通過詳細分析 ILGenerator 的使用方法和方法調用指令,讀者可以更深入地瞭解.NET平臺下動態生成代碼的實現機制。通過本文的閱讀,讀者可以更加熟練地使用 ILGenerator 來動態生成高效、靈... ...
  • 自上一個系列文章寫完之後,最近的兩三個月時間,一直在寫WPF相關技術文章,斷斷續續地寫了近二十幾篇文章,為了方便大家閱讀,現將本系列文章分類整理,彙總如下。 ...
  • 今天給大家上個硬貨,下拉多選框,同時也是下拉多選樹,支持父節點跟子節點!該控制項是基於Telerik控制項封裝實現的,所以大家在使用的過程中需要引用Telerik.WinControls.dll、Telerik.WinControls.UI.dll,還有一些相關的類庫,大家有需要的可以去網上自己找,另外 ...
一周排行
    -Advertisement-
    Play Games
  • 基於.NET Framework 4.8 開發的深度學習模型部署測試平臺,提供了YOLO框架的主流系列模型,包括YOLOv8~v9,以及其系列下的Det、Seg、Pose、Obb、Cls等應用場景,同時支持圖像與視頻檢測。模型部署引擎使用的是OpenVINO™、TensorRT、ONNX runti... ...
  • 十年沉澱,重啟開發之路 十年前,我沉浸在開發的海洋中,每日與代碼為伍,與演算法共舞。那時的我,滿懷激情,對技術的追求近乎狂熱。然而,隨著歲月的流逝,生活的忙碌逐漸占據了我的大部分時間,讓我無暇顧及技術的沉澱與積累。 十年間,我經歷了職業生涯的起伏和變遷。從初出茅廬的菜鳥到逐漸嶄露頭角的開發者,我見證了 ...
  • C# 是一種簡單、現代、面向對象和類型安全的編程語言。.NET 是由 Microsoft 創建的開發平臺,平臺包含了語言規範、工具、運行,支持開發各種應用,如Web、移動、桌面等。.NET框架有多個實現,如.NET Framework、.NET Core(及後續的.NET 5+版本),以及社區版本M... ...
  • 前言 本文介紹瞭如何使用三菱提供的MX Component插件實現對三菱PLC軟元件數據的讀寫,記錄了使用電腦模擬,模擬PLC,直至完成測試的詳細流程,並重點介紹了在這個過程中的易錯點,供參考。 用到的軟體: 1. PLC開發編程環境GX Works2,GX Works2下載鏈接 https:// ...
  • 前言 整理這個官方翻譯的系列,原因是網上大部分的 tomcat 版本比較舊,此版本為 v11 最新的版本。 開源項目 從零手寫實現 tomcat minicat 別稱【嗅虎】心有猛虎,輕嗅薔薇。 系列文章 web server apache tomcat11-01-官方文檔入門介紹 web serv ...
  • 1、jQuery介紹 jQuery是什麼 jQuery是一個快速、簡潔的JavaScript框架,是繼Prototype之後又一個優秀的JavaScript代碼庫(或JavaScript框架)。jQuery設計的宗旨是“write Less,Do More”,即倡導寫更少的代碼,做更多的事情。它封裝 ...
  • 前言 之前的文章把js引擎(aardio封裝庫) 微軟開源的js引擎(ChakraCore))寫好了,這篇文章整點js代碼來測一下bug。測試網站:https://fanyi.youdao.com/index.html#/ 逆向思路 逆向思路可以看有道翻譯js逆向(MD5加密,AES加密)附完整源碼 ...
  • 引言 現代的操作系統(Windows,Linux,Mac OS)等都可以同時打開多個軟體(任務),這些軟體在我們的感知上是同時運行的,例如我們可以一邊瀏覽網頁,一邊聽音樂。而CPU執行代碼同一時間只能執行一條,但即使我們的電腦是單核CPU也可以同時運行多個任務,如下圖所示,這是因為我們的 CPU 的 ...
  • 掌握使用Python進行文本英文統計的基本方法,並瞭解如何進一步優化和擴展這些方法,以應對更複雜的文本分析任務。 ...
  • 背景 Redis多數據源常見的場景: 分區數據處理:當數據量增長時,單個Redis實例可能無法處理所有的數據。通過使用多個Redis數據源,可以將數據分區存儲在不同的實例中,使得數據處理更加高效。 多租戶應用程式:對於多租戶應用程式,每個租戶可以擁有自己的Redis數據源,以確保數據隔離和安全性。 ...