通过反射动态创建对象、方法

之前做的都是获取特性对象,都是查元数据的信息,现在我们可以通过反射开始动态的去创建对象和方法

1.两种调用无参构造函数的方法:

创建一个DemoClass,里面有无参构造函数和有参构造函数

 public class DemoClass
    {
        public string Name { get; set; }

        public  int Age { get; set; }

        public DemoClass()
        {
            Console.WriteLine("无参构造函数被调用啦");
        }

        public DemoClass(string name,int age)
        {
            this.Name = name;
            this.Age = age;
            Console.WriteLine("有参构造函数被调用了");
        }
    }

(1)通过Assembly无参构造函数创建对象

Assembly assembly= Assembly.GetExecutingAssembly();
object o =assembly.CreateInstance("使用构造函数创建对象.DemoClass");
CreateInstance方法的第一个参数代表了要创建的类型实例的字符串名称(命名空间+类名)。注意到CreateInstance方法返回的是一个Object对象,如果使用还要强制转换一下。
(2)通过用Activator创建对象
object o2 = Activator.CreateInstance(null, "使用构造函数创建对象.DemoClass");

其中CreateInstance的第一个参数是程序集的名称,为null时表示当前程序集;第二个参数是要创建的类型名称。Activator.CreateInstance返回的是一个ObjectHandle对象,必须执行一次Unwrap()才能返回Object类型,进而可以强制转换成其实际类型。ObjectHandle包含在System.Runtime.Remoting命名空间中,可见它是Remoting相关的,实际上ObjectHandle类只是一个对原类型进行了一个包装以便进行封送
运行结果如下:

3.调用带参构造函数创建对象

使用Assembly的createInstance函数进行对象的创建

 public class Program
    {
        static void Main(string[] args)
        {
           Assembly assembly= Assembly.GetExecutingAssembly();
            object[]paramers=new object[2];//创建参数数组,以便传入
            paramers[0] = ".net";
            paramers[1] = 14;
            object o =assembly.CreateInstance("使用构造函数创建对象.DemoClass",true,BindingFlags.Default,null,paramers,null,null);
            DemoClass demo = (DemoClass)o;
            Console.WriteLine("输出对象的信息:Name"+demo.Name+"     Age"+demo.Age);
            Console.ReadKey();
        }
    }

BindingFlags.Default不使用任何类型搜索策略。执行结果:

4.动态调用方法

在上面的DemoClass中添加两个方法

        public int Add(int x, int y)
        {
            Console.WriteLine("实例方法被调用");
            return x + y;
        }

        public static void Add(double x, double y)
        {
            Console.WriteLine("静态函数被调用");
        }

(1)Type.InvokeMember调用实例方法

   public class Program
    {
        static void Main(string[] args)
        {
            Type t = typeof(DemoClass);
            DemoClass demo=new DemoClass();
            object[]parameters={1,2};
            object result=t.InvokeMember("Add", BindingFlags.InvokeMethod, null, demo, parameters);
            Console.WriteLine("调用实例方法返回的结果:"+result);
            Console.ReadKey();
        }
    }

第一个参数是指要调用的方法名,第二个参数是要调用方法,第三个Bingder几乎永远传null,第四个是指要在哪个实例上操作,咱们新建的对象demo,最后一个参数是方法的传入参数。InvokeMember方法被调用后返回执行结果。

(2)使用Type.InvokeMember调用静态方法

    public class Program
    {
        static void Main(string[] args)
        {
            Type t = typeof(DemoClass);
            object[]parameters={1.0,2.0};
            object result=t.InvokeMember("Add", BindingFlags.InvokeMethod, null, t, parameters);
            Console.ReadKey();
        }
    }

调用静态方法时与调实例方法差别在第四个参数上,调静态方法只需要传递类型就可以。

5.使用MethodInfo.Invoke调用方法

先获取一个MethodInfo实例,然后调用该实例的Invoke方法

(1)调用实例方法

    public class Program
    {
        private static void Main(string[] args)
        {
            Type t = typeof(DemoClass);
            object[] parameters = { 1, 2 };
            DemoClass demo = new DemoClass();
            MethodInfo info = t.GetMethod("Add", BindingFlags.Instance | BindingFlags.Public);
            info.Invoke(demo, parameters);
            Console.ReadKey();
        }
    }

因为方法中存在多个“Add”方法,所以在GetMethod中加BindingFlags中是必要的,Invoke方法第一个参数是要在那个实例上调用该方法,第二个参数时参数列表。Invoke返回方法执行结果。

(2)调用静态方法

    public class Program
    {
        private static void Main(string[] args)
        {
            Type t = typeof(DemoClass);
            object[] parameters = { 1, 2 };
            MethodInfo info = t.GetMethod("Add", BindingFlags.Static | BindingFlags.Public);
            info.Invoke(null, parameters);
            Console.ReadKey();
        }
    }

调用静态方法与实例方法的区别在于在用BingdingFlags进行搜索时要指定搜索Static,另外Invoke的时候不需要再传入类型的实例了。

6.迟绑定

在我们项目中,各个插件实现了同一个插件接口,再运行时动态的去加载哪个插件,如果不使用反射动态调用的情况下,只能去写多个if else了。编译器在运行前根本不知道去执行哪个方法,称为迟绑定。

时间: 2024-12-24 06:44:11

通过反射动态创建对象、方法的相关文章

【C#反射-动态创建对象】

上面博客学习了使用反射查看类型的信息,以及使用反射获取特性对象. 下面使用反射来动态创建对象.首先准备一个Test类: public class TestClass { public TestClass() { Console.WriteLine("这是一个无参构造函数"); } public TestClass(int a, int b) { Console.WriteLine("这是一个有参数构造函数 > a+b=" + (a + b)); } publi

golang通过反射动态调用方法

func Call(m map[string]interface{}, name string, params ...interface{}) ([]reflect.Value, error) { f := reflect.ValueOf(m[name]) if len(params) != f.Type().NumIn() { return nil, errors.New("the number of input params not match!") } in := make([]

[C#]通过反射动态创建对象

参考链接: https://www.cnblogs.com/codejgq/articles/10163584.html http://www.360doc.com/content/18/0524/09/51449331_756581126.shtml https://www.cnblogs.com/soundcode/p/10722863.html 代码如下: 1 using System; 2 using System.Reflection; 3 using UnityEngine; 4 5

反射之动态创建对象

前言 C#有关反射的话题已经是个老生常谈的话题,也许园友一看这标题都不屑去看了,但是既然拿出来讲必有讲之道理,当然,不喜勿喷,高手请绕道!直入话题. 讨论 定义一个Person类代码如下 1 public class Person 2 { 3 4 /// <summary> 5 /// 年龄 6 /// </summary> 7 public int Age { get; set; } 8 9 /// <summary> 10 /// 姓名 11 /// </su

java动态加载指定的类或者jar包反射调用其方法

序言 有时候,项目中会用到java动态加载指定的类或者jar包反射调用其方法来达到模块的分离,使各个功能之间耦合性大大降低,更加的模块化,代码利用率更高.模式中的代理模式就用到java的这一机制.下边就让我们通过代码来看看如何实现此功能. 代码详细 package loadjarclass; import java.io.File; import java.lang.reflect.Method; import java.net.URL; import java.net.URLClassLoad

java动态载入指定的类或者jar包反射调用其方法

序言 有时候.项目中会用到java动态载入指定的类或者jar包反射调用其方法来达到模块的分离,使各个功能之间耦合性大大减少,更加的模块化.代码利用率更高.模式中的代理模式就用到java的这一机制. 下边就让我们通过代码来看看怎样实现此功能. 代码具体 package loadjarclass; import java.io.File; import java.lang.reflect.Method; import java.net.URL; import java.net.URLClassLoa

使用反射构造对象实例并动态调用方法

在.Net 中,程序集(Assembly)中保存了元数据(MetaData)信息,因此就可以通过分析元数据来获取程序集中的内容,比如类,方法,属性等,这大大方便了在运行时去动态创建实例. MSDN解释如下: 反射提供了封装程序集.模块和类型的对象(Type 类型).可以使用反射动态创建类型的实例,将类型绑定到现有对象,或从现有对象获取类型并调用其方法或访问其字段和属性.如果代码中使用了属性,可以利用反射对它们进行访问. 主要用途: 动态加载DLL,实现插件机制. 实例化DLL中的类型. 执行后期

java 反射机制获取类名、属性、方法、构造器和反射动态使用

被反射的类: @Table("tb_student") public class Student { @Fields(columnName="id",type="int",length=10) private int id; @Fields(columnName="studentName",type="varchar",length=10) private String studentName; @Fiel

C# - 使用配置文件和反射来创建对象实例

使用配置文件和反射来创建对象实例 为了增加程序的可扩展性,提高可配置性,常常需要使用配置文件+反射来动态调用方法. 下面定义的SIT类包含一个接口方法,演示如何使用配置文件及反射来动态调用. using System; namespace ConsoleApp1.CRMDataHandler { public class SIT : CRMDataHandler, IIncident { public void CreateIncident() { Console.WriteLine("{0}