C#反射的Assembly的簡單應用

  反射(Reflection)是.NET中的重要機制,經過反射,能夠在運行時得到.NET中每個類型(包括類、結構、委託、接口和枚舉等)的成員,包括方法、屬性、事件,以及構造函數等。還能夠得到每一個成員的名稱、限定符和參數等。有了反射,便可對每個類型瞭如指掌。若是得到了構造函數的信息,便可直接建立對象,即便這個對象的類型在編譯時還不知道。

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實例化會致使性能降低。

相關文章
相關標籤/搜索