一个例子:C#语言使用反射调用指定类内的函数

今天研究了一下,当指定程序集、类全名、方法名时,给定一个该类的实例,如何调用该实例中指定的方法。

这个功能的背景是这样的:

1、程序中有多个窗体(都继承自Form),保存在一个数组中

2、因为作为父类的Form我是不能新加入任何方法的,所以代码都是现在每个具体的页面里,也就是说,我们只能在子类中写代码,而不能在基类中写代码

3、每个页面(如FormA、FormB)都有一个功能,实现一个同一名称的函数

4、获取FormA、FormB的实例后,要做到调用这些页面内在第3步中指定名称的函数

这个功能抽象一下,可以表述为:给定程序集、类名、指定的函数名,我们要想办法在得到这个类的实例时,调用到指定的函数


示例程序如下:

设立一个程序集InvokeTester

231529_8v1v_1425762.png

里面实现基类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();
        }
    }
}

这段代码的执行结果如下:

232157_KzPc_1425762.png

使用本方法还需要注意一点:

如果被调用的方法在不同的程序集内,请确保这个程序集只生成一个DLL。如果这个程序集生成了多个DLL(可能因为多个生成目标地址不用的程序集都依赖于这个程序集,导致这个程序集的DLL散落在多处),那么在调用MethodInfo类的Invoke函数时可能会报错,异常信息为:“对象与目标类型不匹配”。

END

转载于:https://my.oschina.net/Tsybius2014/blog/602117

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值