C#中Assembly類的使用小結(jié)
Assembly 類位于 System.Reflection 命名空間,表示一個(gè)可重用、可部署且可版本化的 .NET 程序集。程序集是 .NET 應(yīng)用程序的基本構(gòu)建塊,包含了類型、資源、元數(shù)據(jù)和清單。通過 Assembly 類,你可以加載程序集、查詢類型信息、動(dòng)態(tài)創(chuàng)建實(shí)例、讀取自定義特性、訪問嵌入資源等。
1. 如何獲取Assembly對(duì)象
1.1 靜態(tài)方法(常用)
| 方法 | 說明 |
|---|---|
| Assembly.GetExecutingAssembly() | 獲取當(dāng)前正在執(zhí)行的代碼所在的程序集。 |
| Assembly.GetCallingAssembly() | 獲取調(diào)用當(dāng)前方法的方法所在的程序集(性能稍差,慎用)。 |
| Assembly.GetEntryAssembly() | 獲取應(yīng)用程序的入口程序集(通常是可執(zhí)行文件)。 |
| Assembly.Load() | 通過程序集的顯示名稱或字節(jié)數(shù)組加載程序集。 |
| Assembly.LoadFrom() | 從指定文件路徑加載程序集(會(huì)加載依賴項(xiàng))。 |
| Assembly.LoadFile() | 僅加載指定路徑的程序集,不自動(dòng)加載依賴項(xiàng)。 |
| Assembly.ReflectionOnlyLoadFrom() | 僅用于反射(不可執(zhí)行代碼),.NET Core 5+ 不支持。 |
using System.Reflection;
?
// 1. 獲取當(dāng)前程序集
Assembly asm1 = Assembly.GetExecutingAssembly();
?
// 2. 通過名稱加載(需已存在于應(yīng)用程序域)
Assembly asm2 = Assembly.Load("System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089");
?
// 3. 從文件加載
Assembly asm3 = Assembly.LoadFrom(@"C:\MyLibs\MyLibrary.dll");
?
// 4. 獲取入口程序集
Assembly entryAsm = Assembly.GetEntryAssembly();1.2 通過類型獲取
Assembly asm4 = typeof(MyClass).Assembly;
2. 常用屬性
| 屬性 | 說明 |
|---|---|
| FullName | 程序集完整顯示名稱(包含名稱、版本、區(qū)域、公鑰令牌)。 |
| Location | 程序集文件在磁盤上的物理路徑(若已加載)。 |
| CodeBase | 程序集的原始 URI 位置(已過時(shí),建議用 Location)。 |
| ImageRuntimeVersion | 程序集生成時(shí)使用的 CLR 版本(如 v4.0.30319)。 |
| EntryPoint | 返回程序集入口方法(如 Main 方法),若無則返回 null。 |
| IsDynamic | 指示程序集是否通過反射發(fā)出(Reflection.Emit)動(dòng)態(tài)生成。 |
Console.WriteLine(asm1.FullName); // "MyApp, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" Console.WriteLine(asm1.Location); // "C:\MyApp\bin\Debug\MyApp.exe" Console.WriteLine(asm1.ImageRuntimeVersion);// "v4.0.30319"
3. 常用方法
3.1 類型反射
| 方法 | 說明 |
|---|---|
| GetTypes() | 獲取程序集中定義的所有公共類型。 |
| GetExportedTypes() | 獲取程序集中定義的公共類型(可被外部訪問)。 |
| GetType(string name) | 通過類型全名獲取 Type 對(duì)象。 |
| GetReferencedAssemblies() | 獲取當(dāng)前程序集引用的所有程序集名稱(AssemblyName)。 |
Type[] allTypes = asm1.GetTypes();
foreach (Type t in allTypes)
{
Console.WriteLine(t.FullName);
}
?
Type myType = asm1.GetType("MyNamespace.MyClass");3.2 動(dòng)態(tài)創(chuàng)建實(shí)例
| 方法 | 說明 |
|---|---|
| CreateInstance(string typeName) | 創(chuàng)建指定類型(區(qū)分大小寫)的實(shí)例,返回 object。 |
| CreateInstance(string typeName, bool ignoreCase) | 是否忽略大小寫。 |
| CreateInstance(string typeName, bool ignoreCase, BindingFlags binder, object[] args, CultureInfo culture) | 完整重載,支持參數(shù)傳遞。 |
// 創(chuàng)建無參實(shí)例
object obj = asm1.CreateInstance("MyNamespace.MyClass");
?
// 創(chuàng)建帶參數(shù)的實(shí)例
object obj2 = asm1.CreateInstance(
"MyNamespace.MyClass",
false,
BindingFlags.Default,
null,
new object[] { 42, "hello" },
null,
null);3.3 讀取自定義特性
| 方法 | 說明 |
|---|---|
| GetCustomAttributes() | 獲取程序集上定義的所有自定義特性。 |
| GetCustomAttributes(Type attributeType) | 獲取指定類型的特性。 |
| GetCustomAttributesData() | 獲取特性數(shù)據(jù)(不創(chuàng)建實(shí)例,適用于僅反射場(chǎng)景)。 |
// 獲取程序集的 AssemblyTitle 特性 var titleAttr = asm1.GetCustomAttribute<AssemblyTitleAttribute>(); Console.WriteLine(titleAttr?.Title);
3.4 訪問嵌入資源
| 方法 | 說明 |
|---|---|
| GetManifestResourceNames() | 獲取程序集中所有嵌入資源的名稱。 |
| GetManifestResourceStream(string name) | 獲取嵌入資源的數(shù)據(jù)流(Stream)。 |
| GetManifestResourceInfo(string name) | 獲取資源的位置等信息。 |
// 列出所有嵌入資源
string[] resources = asm1.GetManifestResourceNames(); //獲取程序集中所有嵌入資源的名稱
foreach (string res in resources)
{
Console.WriteLine(res);
}
?
// 讀取文本資源
using (Stream stream = asm1.GetManifestResourceStream("MyApp.Resources.Config.xml"))
using (StreamReader reader = new StreamReader(stream))
{
string content = reader.ReadToEnd();
}注意:資源名稱通常是命名空間.文件夾名.文件名,需準(zhǔn)確指定。
3.5 安全性
| 方法 | 說明 |
|---|---|
| Evidence | 獲取程序集的證據(jù)(用于安全策略,已過時(shí))。 |
| PermissionSet | 獲取程序集所需的權(quán)限集。 |
4. 完整示例:加載外部程序集并調(diào)用方法
using System;
using System.Reflection;
?
public class Program
{
public static void Main()
{
// 1. 從文件加載程序集
Assembly pluginAsm = Assembly.LoadFrom(@"C:\Plugins\Calculator.dll");
?
// 2. 獲取類型
Type calcType = pluginAsm.GetType("CalculatorLib.Calculator");
if (calcType == null)
{
Console.WriteLine("類型未找到");
return;
}
?
// 3. 創(chuàng)建實(shí)例
object calculator = Activator.CreateInstance(calcType);
// 或使用 assembly.CreateInstance:
// object calculator = pluginAsm.CreateInstance("CalculatorLib.Calculator");
?
// 4. 調(diào)用方法
MethodInfo addMethod = calcType.GetMethod("Add", new Type[] { typeof(int), typeof(int) });
int result = (int)addMethod.Invoke(calculator, new object[] { 3, 5 });
Console.WriteLine($"3 + 5 = {result}");
?
// 5. 讀取程序集特性
var versionAttr = pluginAsm.GetCustomAttribute<AssemblyFileVersionAttribute>();
Console.WriteLine($"插件版本: {versionAttr?.Version}");
}
}5. 注意事項(xiàng)
- 性能:反射(特別是 Invoke)比直接調(diào)用慢得多,應(yīng)避免在性能敏感的循環(huán)中使用。
- 依賴項(xiàng):使用 LoadFrom 時(shí),CLR 會(huì)嘗試加載依賴程序集(從相同目錄或全局程序集緩存)。如果依賴項(xiàng)不在預(yù)期位置,會(huì)引發(fā) FileNotFoundException。
- 多個(gè)上下文:Load 與 LoadFrom 將程序集加載到不同的上下文,可能導(dǎo)致同一程序集被加載兩次。
- 安全性:從不受信任的源加載程序集存在安全風(fēng)險(xiǎn)(可執(zhí)行任意代碼),建議使用 AssemblyLoadContext(.NET Core 3+)隔離。
- 動(dòng)態(tài)程序集:AssemblyBuilder 生成的動(dòng)態(tài)程序集無法保存到文件(除非指定了 RunAndSave 或 Save)。
- .NET Core/.NET 5+ 變更:
- Assembly.CodeBase 和 Assembly.EscapedCodeBase 已過時(shí),改用 Assembly.Location。
- Assembly.LoadFile 在 .NET Core 中行為不同(直接加載,無依賴解析)。
- 推薦使用 AssemblyLoadContext 進(jìn)行高級(jí)程序集加載控制。
6. 總結(jié)
Assembly 類是 .NET 反射機(jī)制的核心入口之一。掌握它,你就能動(dòng)態(tài)地探索和操作程序集,實(shí)現(xiàn)插件系統(tǒng)、依賴注入、模塊化設(shè)計(jì)、資源提取等功能。關(guān)鍵要理解如何獲取程序集對(duì)象、查詢?cè)獢?shù)據(jù)、創(chuàng)建實(shí)例和訪問嵌入資源,同時(shí)注意性能和安全陷阱。
通過 Assembly 類,你幾乎可以獲取關(guān)于程序集的一切信息,是 .NET 高級(jí)編程的必備技能。
代碼文件”與“運(yùn)行進(jìn)程”**的關(guān)系:
| 屬性 | 定義 | 現(xiàn)場(chǎng)實(shí)操中的含義 |
| Assembly.GetExecutingAssembly().Location | 當(dāng)前代碼程序集(.dll 或 .exe)所在的磁盤絕對(duì)路徑。 | 它是靜態(tài)的“家”。你通過哪個(gè)文件啟動(dòng),它就指哪里。 |
| currentProcess.MainModule.FileName | 當(dāng)前操作系統(tǒng)進(jìn)程對(duì)應(yīng)的可執(zhí)行文件路徑。 | 它是動(dòng)態(tài)的“身份證明”。Windows 記錄了這個(gè)進(jìn)程是從哪個(gè) .exe 運(yùn)行起來的。 |
到此這篇關(guān)于C#中Assembly類的使用小結(jié)的文章就介紹到這了,更多相關(guān)C# Assembly類內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C#編程實(shí)現(xiàn)向并口設(shè)備發(fā)送指令、獲取并口設(shè)備的狀態(tài)
這篇文章主要介紹了C#編程實(shí)現(xiàn)向并口設(shè)備發(fā)送指令、獲取并口設(shè)備的狀態(tài),本文直接給出實(shí)例代碼,需要的朋友可以參考下2015-06-06
操作XML文檔遇到的XMLNS問題及解決方法 (C# 和 PHP)
不管是用 PHP 還是 C#, 在操作 XML 的時(shí)候我們除了一個(gè)節(jié)點(diǎn)一個(gè)節(jié)點(diǎn)去取值之外, 還有一個(gè)非常方便的表達(dá)式, 就是 XPATH2011-05-05
c#委托把方法當(dāng)成參數(shù)(實(shí)例講解)
本篇文章主要是對(duì)c#委托把方法當(dāng)成參數(shù)的實(shí)例代碼進(jìn)行了介紹,需要的朋友可以過來參考下,希望對(duì)大家有所幫助2014-01-01
C#利用WinForm實(shí)現(xiàn)查看指定目錄下所有圖片功能
Windows 窗體是用于生成 Windows 桌面應(yīng)用的 UI 框架, 它提供了一種基于 Visual Studio 中提供的可視化設(shè)計(jì)器創(chuàng)建桌面應(yīng)用的高效方法,本文介紹了C#利用WinForm實(shí)現(xiàn)可以查看指定目錄文件下所有圖片功能,需要的朋友可以參考下2024-05-05

