C#通過反射獲取類中的方法和引數個數,反射呼叫方法帶引數

風靈使發表於2018-05-06
using System;
using System.Reflection;

namespace ConsoleApp2
{
    class Program
    {
        static void Main(string[] args)
        {
            //反射獲取 名稱空間+類名
            string className = "ConsoleApp2.ClassSample";
            string methodName = "test1";
            //傳遞引數
            Object[] paras = new Object[] { "我的", "電腦" };
            var t = Type.GetType(className);
            object obj = Activator.CreateInstance(t);

            try
            {
                #region 方法一
                //直接呼叫
                MethodInfo method = t.GetMethod("test2");
                method.Invoke(obj, paras);
                #endregion

                #region 方法二
                MethodInfo[] info = t.GetMethods();
                for (int i = 0; i < info.Length; i++)
                {
                    var md = info[i];
                    //方法名
                    string mothodName = md.Name;
                    //引數集合
                    ParameterInfo[] paramInfos = md.GetParameters();
                    //方法名相同且引數個數一樣
                    if (mothodName == methodName && paramInfos.Length == paras.Length)
                    {
                        md.Invoke(obj, paras);
                    }
                }
                #endregion
            }
            catch (Exception ex)
            {
                throw ex;
            }
            Console.ReadKey();
        }
    }

    class ClassSample
    {
        public void test1(string para1)
        {
            Console.WriteLine("方式1 {0}________test111", para1);
        }

        public void test1(string para1, string para2)
        {
            Console.WriteLine("方式2 {0}________test111________{1}", para1, para2);
        }

        public void test2(string para1, string para2)
        {
            Console.WriteLine("方式3 {0}________test222________{1}", para1, para2);
        }
    }
}

在C#中,我們要使用反射,首先要搞清楚以下名稱空間中幾個類的關係:

System.Reflection名稱空間

(1) AppDomain:應用程式域,可以將其理解為一組程式集的邏輯容器

(2) Assembly:程式集類

(3) Module:模組類

(4) Type:使用反射得到型別資訊的最核心的類

他們之間是一種從屬關係,也就是說,一個AppDomain可以包含N個Assembly,一個Assembly可以包含N個Module,而一個Module可以包含N個Type.

在程式中,如果我們要動態載入一個程式集有以下種方式可以使用,分別是LoadLoadFromLoadFileLoadWithPartialName方法.

其中著重講解以下Assembly.LoadFileAssembly.LoadFrom的區別

1、Assembly.LoadFile只載入相應的dll檔案,比如Assembly.LoadFile("abc.dll"),則載入abc.dll,假如abc.dll中引用了def.dll的話,def.dll並不會被載入。

Assembly.LoadFrom則不一樣,它會載入dll檔案及其引用的其他dll,比如上面的例子,def.dll也會被載入。

2、用Assembly.LoadFrom載入一個Assembly時,會先檢查前面是否已經載入過相同名字的Assembly,比如abc.dll有兩個版本(版本1在目錄1下,版本2放在目錄2下),程式一開始時載入了版本1,當使用Assembly.LoadFrom("2\\abc.dll")載入版本2時,不能載入,而是返回版本1。Assembly.LoadFile的話則不會做這樣的檢查,比如上面的例子換成Assembly.LoadFile的話,則能正確載入版本2。

LoadFile:載入指定路徑上的程式集檔案的內容。LoadFrom: 根據程式集的檔名載入程式集檔案的內容。

最後是呼叫方法

Assembly outerAsm = Assembly.LoadFrom(@"urPath\MyDLL.dll");

呼叫DLL類中的方法

Type type = outerAsm .GetType("MyDLL.MyClass");//呼叫型別
MethodInfo method = type.GetMethod("MyVoid");//呼叫方法
//如果需要傳引數

object[] paramertors = new object[] { "3087", "2005" };//引數集合
object test = method.Invoke(null, paramertors);//Invoke呼叫方法

呼叫DLL中窗體

Type outerForm = outerAsm.GetType("MyForm", false);//找到指定視窗
(Activator.CreateInstance(outerForm) as Form).Show();//轉換成窗體類,顯示

相關文章