Assembly就是反應反射的一種應用,它定義和加載程序集,加載在程序集清單中列出模塊,以及今後程序集中查找類型並建立該類型的實例。簡單地說就是,使用Assembly在程序中你不用事先寫好比下面的東西了:html
PersonClass person = new PersonClass(); person.Method();
你只要知道PersonClass這個類的程序集,命名空間和類名直接使用反射就可使用。你只須要這樣寫:ide
PersonClass person; person = person = (PersonClass)(Assembly.Load("程序集").CreateInstance("命名空間.類名", false, BindingFlags.Default, null, args, null, null)); person.Method();
下面用一個小例子來看看Assembly應用的方便性。函數
需求:有幾種文件格式,後綴分別是.One,.Two,.Three,... 有不少種,後續還可能增長。這些文件的格式都不同,也就是說讀取方式就不同。那麼根據傳入的文件後綴和路徑讀出文件的內容。性能
實現:spa
這種需求的特色是,根據選擇作不一樣的處理,可是都是出的一種結果,那麼可使用簡單工廠模式來完成。code
讀取文件有一個父類FileSuper,內部以下:xml
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,以下:htm
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實例化會致使性能降低。