一個例子:C#語言使用反射調用指定類內的函數

jopen 8年前發布 | 24K 次閱讀 .NET開發

今天研究了一下,當指定程序集、類全名、方法名時,給定一個該類的實例,如何調用該實例中指定的方法。

這個功能的背景是這樣的:

1、程序中有多個窗體(都繼承自Form),保存在一個數組中

2、因為作為父類的Form我是不能新加入任何方法的,所以代碼都是現在每個具體的頁面里,也就是說,我們只能在子類中寫代碼,而不能在基類中寫代碼

3、每個頁面(如FormA、FormB)都有一個功能,實現一個同一名稱的函數

4、獲取FormA、FormB的實例后,要做到調用這些頁面內在第3步中指定名稱的函數

這個功能抽象一下,可以表述為:給定程序集、類名、指定的函數名,我們要想辦法在得到這個類的實例時,調用到指定的函數


示例程序如下:

設立一個程序集InvokeTester

里面實現基類Vehicle

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace InvokeTester
{
    public class Vehicle
    {
        public Vehicle(string brand, string model)
        {
            this.Brand = brand;
            this.Model = model;
        }

        /// <summary>
        /// 商標
        /// </summary>
        private string _brand;
        /// <summary>
        /// 商標
        /// </summary>
        public string Brand
        {
            get { return _brand; }
            private set { _brand = value; }
        }

        /// <summary>
        /// 型號
        /// </summary>
        private string _model;
        /// <summary>
        /// 型號
        /// </summary>
        public string Model
        {
            get { return _model; }
            private set { _model = value; }
        }
    }
}

Vehicle下有子類Truck:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace InvokeTester
{
    public class Truck : Vehicle
    {
        public Truck(string brand, string model, string purpose)
            : base(brand, model)
        {
            this.Purpose = purpose;
        }

        /// <summary>
        /// 用途
        /// </summary>
        private string _purpose;
        /// <summary>
        /// 用途
        /// </summary>
        public string Purpose
        {
            get { return _purpose; }
            private set { _purpose = value; }
        }

        public string GetDescription()
        {
            return string.Format("商標:{0},型號:{1},用途:{2}", Brand, Model, Purpose);
        }
    }
}

現在要做的,是在一個以Vehicle類保存的Truck類實例中,給定程序集名稱InvokeTester、類名Truck、方法名GetDescription,調用GetDescription方法。代碼如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace InvokeTester
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                string dllName = "InvokeTester"; //程序集名
                string className = "InvokeTester.Truck"; //類全名
                string methodName = "GetDescription"; //方法名

                //調用對象的指定方法
                Vehicle vehicle = new Truck("大象牌", "DX001", "起重機");
                Assembly assembly = Assembly.Load(dllName);
                if (assembly != null)
                {
                    Type type = assembly.GetType(className);
                    if (type != null)
                    {
                        MethodInfo methodInfo = type.GetMethod(methodName);
                        if (methodInfo != null)
                        {
                            string desc = methodInfo.Invoke(vehicle, null).ToString();
                            Console.WriteLine(desc);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }

            Console.Read();
        }
    }
}

這段代碼的執行結果如下:

使用本方法還需要注意一點:

如果被調用的方法在不同的程序集內,請確保這個程序集只生成一個DLL。如果這個程序集生成了多個DLL(可能因為多個生成目標地址不用的程序集都依賴于這個程序集,導致這個程序集的DLL散落在多處),那么在調用MethodInfo類的Invoke函數時可能會報錯,異常信息為:“對象與目標類型不匹配”。

END

來自: http://my.oschina.net/Tsybius2014/blog/602117

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!