如何通过反射

时间:2015-09-08 14:14:19

标签: c# reflection

我正在尝试理解反射C#,特别是在我的程序中加载第三方dll。 我创建了一个简单的DLL:

namespace testclass
{
    public class Class1
    {
        private string f;
        public string f1 { get; set; }
    }

    public class Class2
    {
        public static int f2 = 0;
        public static string f1 { get; set; }

        static Class2()
        {
            Console.WriteLine("1st string");
        }

        public  void runme()
        {
            Console.WriteLine("2nd string");       
        }
    }
}

并将其加载到我的程序中:

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

class program
{
   static void Main()
    {    
        Assembly assembly;
        assembly = Assembly.LoadFrom(@"D:\user\ClassLibrary1.dll");
        var exporttypes = assembly.GetExportedTypes();
        foreach (var types in exporttypes)
        {
            var fields = types.GetFields();
            foreach (var fi in fields)
            {
                if (fi.Name == "f2")
                {
                    fi.SetValue(exporttypes, 2);
                }
            }
            var m1 = types.GetMethods();
            for (int i = 0; i < m1.Length; i++)
            {
                if (m1[i].Name == "runme")
                {
                    m1[i].Invoke(types, null);
                }
            }
        }

        Console.ReadKey();
    }
}

问题在于,当您尝试调用方法'runme'时,如果'runme'不是静态的,编译器会给出异常。我想了解在这种情况下,您需要传递作为第一个参数来调用

3 个答案:

答案 0 :(得分:4)

要使用反射调用非静态方法,您必须创建该类型的实例,并将其作为第一个参数传递给Invoke

因此,就您的代码而言,这可能是

if (m1[i].Name == "runme")
{
    var inst = Activator.CreateInstance(types);
    m1[i].Invoke(inst, null);
}

注意,这只会起作用,因为该类型具有无参数构造函数,并且是从类型创建实例的最基本方法,其他许多存在。

答案 1 :(得分:1)

您需要创建一个对象实例来调用非静态方法:

// Only works if there's a default ctor:
var instance = Activator.CreateInstance(types);

然后将实例传递给您尝试调用的非静态方法:

m1[i].Invoke(instance, null);

注意:您的变量types应该是单数的:theType,例如。

答案 2 :(得分:0)

您需要创建一个实例。

我相信语法是

var instance = Activator.CreateInstance(types).
m1[i].Invoke(instance, null);