程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> C#反射的Assembly的簡單應用

C#反射的Assembly的簡單應用

編輯:C#入門知識

反射(Reflection)是.NET中的重要機制,通過反射,可以在運行時獲得.NET中每一個類型(包括類、結構、委托、接口和枚舉等)的成員,包括方法、屬性、事件,以及構造函數等。還可以獲得每個成員的名稱、限定符和參數等。有了反射,即可對每一個類型了如指掌。如果獲得了構造函數的信息,即可直接創建對象,即使這個對象的類型在編譯時還不知道。
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實例化會導致性能下降。
 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved