C#反射的Assembly的簡單應用
Assembly就是反應反射的一種應用,它定義和載入程式集,載入在程式集清單中列出模組,以及從此程式集中查詢型別並建立該型別的例項。簡單地說就是,使用Assembly在程式中你不用事先寫比如下面的東西了:
- PersonClass person = new PersonClass();
- person.Method();
你只要知道PersonClass這個類的程式集,名稱空間和類名直接使用反射就可以使用。你只需要這樣寫:
- PersonClass person;
- person =
- person = (PersonClass)(Assembly.Load("程式集").CreateInstance("名稱空間.類名", false, BindingFlags.Default, null, args, null, null));
- person.Method();
下面用一個小例子來看看Assembly應用的方便性。
需求:有幾種檔案格式,字尾分別是.One,.Two,.Three,... 有很多種,後續還可能增加。這些檔案的格式都不一樣,也就是說讀取方式就不一樣。那麼根據傳入的檔案字尾和路徑讀出檔案的內容。
實現:
這種需求的特點是,根據選擇做不同的處理,但是都是出的一種結果,那麼可以使用簡單工廠模式來完成。
讀取檔案有一個父類FileSuper,內部如下:
- using System;
- using System.Collections.Generic;
- using System.Text;
- namespace reflect
- {
- public abstract class FileSuper//獲取不同字尾名檔案的內容
- {
- public abstract string GetFileContext(string fileFullPath);
- }
- }
分別有MyFileOne,MyFileTwo,MyFileThree等,繼承FileSuper,如下:
- using System;
- using System.Collections.Generic;
- using System.Text;
- namespace reflect
- {
- public class MyFileOne : FileSuper
- {
- public override string GetFileContext(string fileFullPath)
- {
- return "One型別檔案的內容";
- }
- }
- }
- using System;
- using System.Collections.Generic;
- using System.Text;
- namespace reflect
- {
- public class MyFileTwo : FileSuper
- {
- public override string GetFileContext(string fileFullPath)
- {
- return "Two型別檔案的內容";
- }
- }
- }
- using System;
- using System.Collections.Generic;
- using System.Text;
- namespace reflect
- {
- public class MyFileThree : FileSuper
- {
- public override string GetFileContext(string fileFullPath)
- {
- return "Three型別檔案的內容";
- }
- }
- }
一個工廠類根據字尾名決定例項化哪個類:
- using System;
- using System.Collections.Generic;
- using System.Text;
- namespace reflect
- {
- public class OperationFile
- {
- static FileSuper fileSuper = null;
- public static string GetStringByFile(string fileFullPath, string extendName)
- {
- switch (extendName)
- {
- case "One":
- fileSuper = new MyFileOne();
- break;
- case "Two":
- fileSuper = new MyFileTwo();
- break;
- case "Three":
- fileSuper = new MyFileThree();
- break;
- }
- if (fileSuper != null)
- {
- return fileSuper.GetFileContext(fileFullPath);
- }
- return "沒有指定的型別";
- }
- }
- }
客戶端呼叫,顯示結果:
- using System;
- using System.Collections.Generic;
- using System.Text;
- namespace reflect
- {
- public class Program
- {
- static void Main(string[] args)
- {
- string fileContext = OperationFile.GetStringByFile("路徑", "One");
- Console.WriteLine(fileContext);
- Console.ReadLine();
- }
- }
- }
這樣解決了這個需求,前面在讀書筆記6:工廠方法模式 中提到了這種方式的缺點,就是不符合開放封閉原則,那麼如何改進了,除了工廠方法模式,我們可以使用Assembly。使用它之前,要先寫一個類和一個配置檔案。
先看配置檔案:MyFile.xml
- <?xml version="1.0" encoding="utf-8" ?>
- <FileExtendName>
- <extend>
- <name>One</name>
- <class>MyFileOne</class>
- </extend>
- <extend>
- <name>Two</name>
- <class>MyFileTwo</class>
- </extend>
- <extend>
- <name>Three</name>
- <class>MyFileThree</class>
- </extend>
- </FileExtendName>
是字尾名和類名的對應。
另一個讀取配置檔案的類ExtendNameDataTable。
- using System;
- using System.Collections.Generic;
- using System.Text;
- using System.Data;
- namespace reflect
- {
- public class ExtendNameDataTable
- {
- private static DataSet extendDataSet;
- public static DataSet ExtendDataSet
- {
- get
- {
- if (extendDataSet == null)
- {
- extendDataSet = new DataSet();
- extendDataSet.ReadXml(@"F:\MyFile.xml");
- }
- return extendDataSet;
- }
- }
- }
- }
做好這兩個準備後,只需修改OperationFile工廠類,其餘都不用修改。使用Assembly來根據配置檔案,自動按照傳入的字尾名載入類,並且例項化,修改後的OperationFile如下:
- using System;
- using System.Collections.Generic;
- using System.Text;
- using System.Data;
- using System.Reflection;
- namespace reflect
- {
- public class OperationFile
- {
- public static string GetStringByFile(string fileFullPath, string extendName)
- {
- DataRow dr = ((DataRow[])ExtendNameDataTable.ExtendDataSet.Tables[0].Select("name='" + extendName + "'"))[0];
- object[] args = null;
- FileSuper fileSuper;
- fileSuper = (FileSuper)(Assembly.Load("reflect").CreateInstance(
- "reflect." + dr["class"].ToString(), false, BindingFlags.Default, null, args, null, null));
- return fileSuper.GetFileContext(fileFullPath);
- }
- }
- }
客戶端呼叫不變輸出結果:
我們看到,這樣一來,如果有了新的檔案結構,只需要再寫一個MyFileFour類繼承自FileSuper;然後再在MyFile.xml中增加相應的對應關係就可以了,避免了要修改OperationFile的case分支,符合開放封閉原則。
當然Assembly這麼好使用,也不是所有情況下都能用的,當在迴圈中碰到了這種情況,那麼還是使用簡單工廠模式或者工廠方法模式吧,因為再迴圈中使用Assembly例項化會導致效能下降。
相關文章
- C#反射實現簡單的外掛系統C#反射
- C#反射中Assembly.Load及Assembly.Load.CreateInstance方法介紹C#反射
- 反射的應用反射
- websoket的簡單應用Web
- npm的簡單應用NPM
- C# 輕量級 ORM 框架 NPoco 的簡單應用C#ORM框架
- Java反射的應用Java反射
- B樹概述與簡單應用示例(C#)C#
- jsp的簡單應用JS
- 遞迴的簡單應用遞迴
- rename命令的簡單應用
- 淺談 C# Assembly 與 IL (一):C# Assembly 與 ReflectionC#
- 關於GO反射的簡單定律Go反射
- 一個簡單的iptable的應用
- pythontornodo的簡單應用1Python
- jQuary中ajax的簡單應用
- gRPC的Golang簡單應用RPCGolang
- @Autowire/@Qualifilter/@Resource的簡單應用Filter
- 並查集的簡單應用並查集
- Android ExpandableListView的簡單應用AndroidView
- 簡單的線段樹應用
- Windows Installer的簡單應用Windows
- java反射技術的應用Java反射
- 一個簡單的反射連線程式反射線程
- java 反射簡單使用Java反射
- C#反射基礎知識和實戰應用C#反射
- Android 極簡反射教程及應用示例Android反射
- Disruptor的簡單介紹與應用
- 簡單計算器(棧的應用)
- 簡單易用的macOS音量應用程式Mac
- arguments的應用示例簡單介紹
- libssh2的簡單應用
- 簡單的Java二維碼應用Java
- Rust GUI庫 egui 的簡單應用RustGUI
- 一個簡單的 indexedDB 應用示例Index
- thymeleaf 簡單應用
- div 簡單應用
- ajax簡單應用