C# 反射 相关内容

//

实现原理:在运行时根据程序集及其中的类型得到元数据。下面是实现步骤:

1. 导入using System.Reflection;

2. Assembly.Load(“程序集”)加载程序集,返回类型是一个Assembly

3. 得到程序集中所有类的名称

foreach (Type type in assembly.GetTypes())

{

string t = type.Name;

}

4. Type type = assembly.GetType(“程序集.类名”);获取当前类的类型

5. Activator.CreateInstance(type); 创建此类型实例

6. MethodInfo mInfo = type.GetMethod(“方法名”);获取当前方法

7. m.Info.Invoke(null,方法参数);

理解C#反射机制

反射是.NET中的重要机制,通过反射可以得到*.exe或*.dll等程序集内部的接口、类、方法、字段、属性、特性等信息,还可以动态创建出类型实例并执行其中的方法。
反射的功能很强大,任何复杂抽象的分层架构或者复杂的设计模式均是建立在这些基础之上的,比如我们要进行模块化、组件化开发,要严格的消除模块之间的耦合,要进行动态接口调用。开发这样强大而灵活的系统,必须要用反射才行,我们只要把它用在合适的位置,不仅能使代码变的清晰简洁,更能让它发挥出惊人的力量。

反射的用途
类型    作用
Assembly    定义和加载程序集,加载程序集清单中列出的模块,以及从此程序集中查找类型并创建该类型的实例。
Module    了解包含模块的程序集以及模块中的类等,还可以获取在模块上定义的所有全局方法或其他特定的非全局方法。
ConstructorInfo    了解构造器的名称、参数、访问修饰符(如public或private)和实现详细信息(如abstract或virtual)等。使用Type的GetConstructors或GetConstructor方法来调用特定的构造函数。
MethodInfo    了解方法的名称、返回类型、参数、访问修饰符(如public或private)和实现详细信息(如abstract或virtual)等。使用Type的GetMethods或GetMethod方法来调用特定的方法。
FieldInfo    了解字段的名称、访问修饰符(如public或private)和实现详细信息(如static)等,并获取或设置字段值。
EventInfo    了解事件的名称、事件处理程序数据类型、自定义特性、声明类型和反射类型等,并添加或移除事件处理程序。
PropertyInfo    了解属性的名称、数据类型、声明类型、反射类型和只读或可写状态等,并获取或设置属性值。
ParameterInfo    了解参数的名称、数据类型、参数是输入参数还是输出参数等,以及参数在方法签名中的位置等。
System.Type类
System.Type类对于反射有很重要的作用。它是一个抽象的基类,Type有与每种数据类型对应的派生类,我们使用这个派生类的对象的方法、字段、属性来查找有关该类型的所有信息。
获取给定类型的Type值有三种常用方式:

使用C# typeof运算符
Type t=typeof(string);
使用对象的GetType()方法
string s=”guo”;Type t=s.GetType();
调用Type类的静态方法GetType()
Type t=Type.GetType(“System.String”);
获取程序集信息
namespace ReflectionTest
{
    class ReflectionHelper
    {
        public void GetAssemblyInfo()
        {
            Assembly assembly = Assembly.GetExecutingAssembly();
            Console.WriteLine("程序集全名:{0}", assembly.FullName);
            Console.WriteLine("程序集的版本:{0}", assembly.GetName().Version);
            Console.WriteLine("程序集初始位置:{0}", assembly.CodeBase);
            Console.WriteLine("程序集位置:{0}", assembly.Location);
            Console.WriteLine("程序集入口:{0}", assembly.EntryPoint);
            Type[] types = assembly.GetTypes();
            Console.WriteLine("程序集中包含的类型:");
            foreach (Type item in types)
            {
                Console.WriteLine("类:" + item.Name);
            }
        }
    }
}

 获取类型信息

namespace ReflectionTest
{
    class ReflectionHelper
    {
        public void GetTypeInfo()
        {
            Type type = typeof(Person);
            Console.WriteLine("类型名:{0}", type.Name);
            Console.WriteLine("类全名:{0}", type.FullName);
            Console.WriteLine("命名空间:{0}", type.Namespace);
            Console.WriteLine("程序集名:{0}", type.Assembly);
            Console.WriteLine("模块名:{0}", type.Module);
            Console.WriteLine("基类名:{0}", type.BaseType);
            Console.WriteLine("是否类:{0}", type.IsClass);
            Console.WriteLine("类的公共成员:");
            MemberInfo[] members = type.GetMembers();
            foreach (MemberInfo memberInfo in members)
            {
                Console.WriteLine("{0}:{1}", memberInfo.MemberType, memberInfo);
            }
        }
    }
}

 反射调用方法

namespace ReflectionTest
{
    class ReflectionHelper
    {
        public void InvokeMethod()
        {
            #region 方法一
            Assembly assembly1 = Assembly.Load("ReflectionTest");
            Type type1 = assembly1.GetType("ReflectionTest.Person");
            object obj1 = System.Activator.CreateInstance(type1);
            MethodInfo method1 = type1.GetMethod("Show");
            method1.Invoke(obj1, null);
            #endregion

            #region 方法二
            object obj2 = Assembly.Load("ReflectionTest").CreateInstance("ReflectionTest.Person");
            Type type2 = obj2.GetType();
            MethodInfo method = type2.GetMethod("Show");
            method.Invoke(obj2, null);
            #endregion
        }
    }
}
反射实现工厂模式

namespace ReflectionTest
{
    class Program
    {
        static void Main(string[] args)
        {
            //方法一
            AbsFruit absFruit = FruitFactory.CreateInstance<AbsFruit>("ReflectionTest", "Strawberry");
            absFruit.Show();
            //方法二
            //string fullTypeName = typeof (Strawberry).FullName;
            string fullTypeName = typeof (Strawberry).AssemblyQualifiedName;            
            AbsFruit absFruit2 = FruitFactory.CreateInstance<AbsFruit>(fullTypeName);
            absFruit2.Show();
        }
    }
}
namespace ReflectionTest
{
    public class FruitFactory
    {
        public static T CreateInstance<T>(string nameSpace,string className)
        {
            string fullClassName = nameSpace + "." + className;
            return (T)Assembly.Load(nameSpace).CreateInstance(fullClassName);
        }

        public static T CreateInstance<T>(string fullTypeName)
        {
            return (T)Activator.CreateInstance(Type.GetType(fullTypeName));
        }
    }
}
public abstract class AbsFruit
{
    protected string Name { get; set; }
    public abstract void Show();
}
class Strawberry:AbsFruit
{
    public Strawberry()
    {
        Name = "草莓";
    }
    public override void Show()
    {
        Console.WriteLine("水果类型:" + Name);
    }
}

//

C# 反射机制和作用

第一件事就是:反射很慢,消耗性能。

反射:可以通过程序集,类型,类型实例获取该程序集内【所有类型+类型所有字段+类型字段的类型,方法,方法的访问类型,参数和返回值等等。。。】

作用<1> Json或XML解析,用于实例化一个class类,当然需要该class类和jsondata或XML data的内容相匹配。
评价:很鸡肋的用法——如果你很懒,不想写反射机制的相关代码,完全可以用JsonMapper等工具实现,其内部也是用反射实现的。而且初始化对象可以用二进制序列化文件,比XML和Json高效,可压缩,可加密(protocolBuf或序列化器)

作用<2>应用于工厂 :把要创建的类型的当做参数去创建相应的对象
评价:好的面向对象设计可以避免反射,比如面向抽象编程,面向接口编程
优点:此处反射唯一的好处是可以把创建的类写到Json,通过Assetbunddle download json,可以在游戏发布后还可以控制控制创建物体的类型。

作用<3> 对于第三方插件。比如C++写的DLL,导入DLL后你怎么知道里面包含了哪些类,类的命名空间,哪些字段,字段的类型,哪些方法,方法的参数和返回值?特别是你通过“DLL查看器”,看到一个函数很可能就是你想要的,但是你不知道其参数类型和返回值类型,怎么办?答案就是反射。

//

C# 反射机制以及方法

反射是什么?

反射:通过动态获取程序集,并获取其中的类型元数据,然后访问该类型的过程。

一. 反射的主要特性

在介绍反射的主要特性之前我们先建一个Person类(下面都是对Person类进行操作)

   View Code

1.反射中一个非常重要的类型就是 Type

获取Person类型的Type对象(Type对象中就是存放了一些关于某个类型的所有信息的内容。[某个类型的Type对象就是该类型“类型元数据”])

获取Type对象有两种方法:

1)当没有对象的时候使用这种方式来获取某个类型的Type
Type type = typeof(Person);

2)当已经获得对象后通过对象的GetType()方法来获取指定对象的类型的Type对象
Person p = new Person();
Type personType = p.GetType();
2.获取Person类中的所有的方法

(通过Type对象的GetMethods()可以获取指定类型的所有的方法其中包括编译器自动生成的方法以及从父类中继承来的方法,但是不包含private方法)
MethodInfo[] methods = personType.GetMethods();
for (int i = 0; i < methods.Length; i++)
{undefined
Console.WriteLine(methods[i].Name);
}

3.获取某个类型的所有属性
PropertyInfo[] properties = personType.GetProperties();
for (int i = 0; i < properties.Length; i++)
{undefined
Console.WriteLine(properties[i].Name);
}
Console.ReadKey();
4.获取类中的所有字段,私有字段无法获取
FieldInfo[] fields = personType.GetFields();
for (int i = 0; i < fields.Length; i++)
{undefined
Console.WriteLine(fields[i].Name);
}
Console.ReadKey();
5.获取所有成员,不包含私有成员
MemberInfo[] members = personType.GetMembers();
for (int i = 0; i < members.Length; i++)
{undefined
Console.WriteLine(members[i].Name);
}
Console.ReadKey();

二. 反射动态加载程序集

在接收发射动态加载程序集,先把程序级的代码贴出来(下面都是对程序集TestDll.dll进行操作)

namespace TestDll
{
    public class Class1
    {
    }

    class MyClass
    {
        public void English()
        {
            Console.WriteLine("Hi,English");
        }
    }

    public abstract class MyAbstractClass
    {

    }

    public static class MyStaticClass
    {
    }


    public class Person
    {
        public Person()
        {

        }

        public Person(string name, int age, string email)
        {
            this.Name = name;
            this.Age = age;
            this.Email = email;
        }

        public string Name { get; set; }
        public int Age { get; set; }
        public string Email { get; set; }

        public void GetNameValue()
        {
            Console.WriteLine(this.Name + "--" + this.Age + "--" + this.Email);
        }


        public void English()
        {
            Console.WriteLine("Hi,English");
        }

        public void China()
        {
            Console.WriteLine("你好,中国");
        }

        public int Add(int n1, int n2)
        {
            return n1 + n2;
        }

        public int Add(int n1, int n2, int n3)
        {
            return n1 + n2 + n3;
        }
    }

    public class Student : Person, IFlyable
    {
        public string StudentNo { get; set; }

        #region IFlyable 成员

        public void Fly()
        {
            Console.WriteLine("I can Fly!");
        }

        #endregion
    }

    class Teacher : Person
    {

    }

    public delegate void MyDelegate();

    delegate void MyDelegate1();

    public enum GoodMan
    {
        高,
        富,
        帅
    }

    public interface IFlyable
    {
        void Fly();
    }
}

1.动态加载一个程序集
Assembly assembly = Assembly.LoadFile(@"D:\TestDll\bin\Debug\TestDll.dll"); 

注意:这个地址是程序及所在的绝对地址 


2.获取刚刚加载的程序集中的所有的类型
assembly.GetType() 等价于 typeof(Assembly)
1)GetTypes()获取了所有的类型
Type[] types = assembly.GetTypes();

2)只获取那些public的类型
Type[] types = assembly.GetExportedTypes();
for (int i = 0; i < types.Length; i++)
{undefined
Console.WriteLine(types[i].Name);
}

3.获取程序集中某个类的Type
如:只获取Person类的Type
GetType()方法有重载,选择第二个重载,参数表示是要获取的类型的“完全限定名称”,即:命名空间.类名
这里拿到了Type,其实就等价于typeof(Person)或者是:p.GetType();
Type personType = assembly.GetType("_02TestDll.Person");

获取所有的方法:personType.GetMethods();

4.动态调用类的方法

(借用上面获取的Person类的方法)

获取某个特定的方法(根据方法名):personType.GetMethod(); 

1)调用无参数无返回值的方法

MethodInfo method = personType.GetMethod("SayHi");
Console.WriteLine(method.Name);

//通过反射来创建一个Person类型的对象{其实就是通过Person的Type来创建一个Person对象}

object objPerson = Activator.CreateInstance(personType);

//调用这个方法
method.Invoke(objPerson, null);

2) 调用带参数,带返回值的方法

1> 调用不带重载的方法
//找到对应的方法
MethodInfo method = personType.GetMethod("Add");
object obj = Activator.CreateInstance(personType);
//调用
object result = method.Invoke(obj, new object[] { 102, 203 });
Console.WriteLine("调用Add方法的返回值结果是:{0}", result);
#endregion
2>调用带重载的方法

//找到对应的方法
MethodInfo method = personType.GetMethod("Add", new Type[] { typeof(int), typeof(int), typeof(int) });
object obj = Activator.CreateInstance(personType);

//调用
int r = (int)method.Invoke(obj, new object[] { 1, 2, 3 });
Console.WriteLine(r);

5. 通过反射获取类的属性,并赋值

(借用上面获取的Person类的方法)

1)获取Name属性
PropertyInfo property = personType.GetProperty("Name");
object obj = Activator.CreateInstance(personType);
2)为属性赋值
property.SetValue(obj, "张三", null);

3) 获取属性值
string name = property.GetValue(obj, null).ToString();
Console.WriteLine(name);

4)获取方法并调用

MethodInfo method = personType.GetMethod("GetNameValue");
method.Invoke(obj, null);
Console.ReadKey();
6.手动查找类型的构造函数,并且调用该构造函数来创建类型的对象

查找到了对应的构造函数,但是还没有调用
ConstructorInfo ctor = personType.GetConstructor(new Type[] { typeof(string), typeof(int), typeof(string) });

开始调用构造函数
object obj = ctor.Invoke(new object[] { "hpp", 16, "hpp@yahoo.com" });
Console.WriteLine(obj.ToString());

MethodInfo method = personType.GetMethod("GetNameValue");
method.Invoke(obj, null);
Console.ReadKey();

三. 其他的反射中的一些方法

//动态加载一个程序集
Assembly assembly = Assembly.LoadFile(@"D:\TestDll\bin\Debug\TestDll.dll");

//获取类的Type 
Type typePerson = assembly.GetType("TestDll.Person");

Type typeStudent = assembly.GetType("TestDll.Student");

Type typeIFlyable = assembly.GetType("TestDll.IFlyable");

1. bool IsAssignableFrom(Type c) 判断当前的类型的变量是不是可以接受c类型变量的赋值


//表示可以将Student类型赋值给Person类型,因为Student类型继承自Person类
bool b = typePerson.IsAssignableFrom(typeStudent); //true

//表示可以将Student类型赋值给IFlyable类型,因为Student类型继承自IFlyable接口

bool b = typeIFlyable.IsAssignableFrom(typeStudent);//true

//表示不可以将Person类型赋值给IFlyable类型,因为Person类型没有继承IFlyable接口

bool b = typeIFlyable.IsAssignableFrom(typePerson);//false

2. bool IsInstanceOfType(object o):判断对象o是否是当前类的实例(当前类可以是o的类、父类、接口)

//Person
object objPerson = Activator.CreateInstance(typePerson);
//Student
object objStudent = Activator.CreateInstance(typeStudent);

//当前类就是Person类

bool b = typePerson.IsInstanceOfType(objPerson);//true

//Suntent类是Person类的子类

bool b = typePerson.IsInstanceOfType(objStudent);//true

//person类不是Student的子类

bool b = typeStudent.IsInstanceOfType(objPerson);//false

3. bool IsSubclassOf(Type c):判断当前类是否是类c的子类

//Person
object objPerson = Activator.CreateInstance(typePerson);
//Student
object objStudent = Activator.CreateInstance(typeStudent);

//Suntent类是Person类的子类

bool b = typeStudent.IsSubclassOf(typePerson);//true

//person类不是Student的子类

 bool b = typePerson.IsSubclassOf(typeStudent);//false

//这个返回是false,只验证类与类之间的父子类关系,接口不包含。
bool b = typeStudent.IsSubclassOf(typeIFlyable);

4. IsAbstract 判断是否为抽象的,含接口

Type typeMyAbsClass = assembly.GetType("TestDll.MyAbstractClass");
Type typeMyStaticClass = assembly.GetType("TestDll.MyStaticClass");

Console.WriteLine(typePerson.IsAbstract);//false;
Console.WriteLine(typeStudent.IsAbstract);//false
Console.WriteLine(typeIFlyable.IsAbstract);//true
Console.WriteLine(typeMyAbsClass.IsAbstract);//true
Console.WriteLine(typeMyStaticClass.IsAbstract); //true
Console.ReadKey();

浅谈反射机制

什么是反射?

        反射提供了封装程序集、模块和类型的对象(Type 类型)。可以使用反射动态创建类型的实例,将类型绑定到现有对象,或从现有对象获取类型并调用其方法或访问其字段和属性。如果代码中使用了属性,可以利用反射对它们进行访问。

        反射机制是.Net中获取运行时类型信息的方式,.Net的应用程序由几个部分:‘程序集(Assembly)’、‘模块(Module)’、‘类型(class)’组成,而反射提供一种编程的方式,让程序员可以在程序运行期获得这几个组成部分的相关信息。

        通俗的来讲,就是反射是通过一个对象去了解另一个对象的内部结构和信息,即使在你不知道那个对象存在的情况下。就好比是海船的声纳探测一样,我们并不知道海水深处是什么情况,但是通过声呐反射回来的情况,就可以掌握障碍物的大小,移动速度等等,和我们所谈论的反射是一个道理。但是我们在程序使用反射不仅可以获取,类的内部情况,还可以操作调用反射类的方法,简直是太神奇了。

为什么用反射?

        1使用了反射后,你的程序在更新的时候无需重新编译,只要将更新的Dll换掉即可完成程序的更新和升级。

        2将反射和配置文件相结合,可以开发出功能随意增删改的软件,具备了极大地灵活性和扩展性。

        3反射提高了程序的灵活性,降低了耦合性,提高了自适应能力,同时也大大提高了程序的复用性。

        但是要强调的一点是,任何事物都有两面性,不是所有场合都适合使用反射技术的。使用反射也会有其缺点:

        1首先带来的一个很大的问题就是——性能问题,使用反射基本上是一种解释操作,用于字段和方法接入时要远慢于直接代码。

        2使用反射会使程序内部逻辑模糊化,程序员在调试代码的时候西瓦昂看到清晰的程序逻辑,而反射却绕过了源代码,因此会带来一定的维护性问题,同时反射代码比相应的直接代码更加复杂。

        综上所述:反射机制有其适用的场合,只要用来开发对灵活性和扩展性要求很高的软件系统,普通的程序没必要使用。

        怎么用反射?

        首先声明我对反射的使用不是很深入,只是做了一些简单的尝试,下面用一个小Demo来说明如何在C#中使用反射获取一个类的属性、方法以及修改属性和调用方法等。代码如下:

        首先我们先写一个目标类Student     
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
 
namespace ITOO.Reflection.Student
{
    public class Student
    {
        public string Name { get; set; }
 
        public int Age { get; set; }
 
        // 默认构造函数
        public Student()
        {
            this.Age = 24;
            this.Name = "连江伟";
        }
        //带参数的构造函数
        public Student(string name,int age)
        {
            this.Name = name;
            this.Age = age;
        }
 
        public void Hello()
        {
            Console.WriteLine("我是"+Name +",我今年"+Age +"岁了!");
        }
    }
}
然后我们在控制台应用程序中去利用反射操纵这个类 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
 
namespace ITOO.Reflection.Client
{
    class Program
    {
        static void Main(string[] args)
        {
            //动态加载DLL,这个LoadFile最方便,参数就是dll的路径。
            var asm = Assembly.LoadFile(@"C:\Users\ljw\Desktop\学习例子\ITOO.Reflection.Test\ITOO.Reflection.Student\bin\Debug\ITOO.Reflection.Student.dll");
            //获取Student类的类型
            var type = asm.GetType("ITOO.Reflection.Student.Student");
            //创建该类的实例
            var instance = asm.CreateInstance("ITOO.Reflection.Student.Student");
            //为学生类的属性赋值
            type.GetProperty("Name").SetValue(instance, "段天涯", null);
            type.GetProperty("Age").SetValue(instance, 18, null);
            //获取Student类的方法
            var method = type.GetMethod("Hello");
            //调用Student类的成员方法Hello
            method.Invoke(instance, null);
            Console.Read();
        }
    }
}
 

///

C#中几种反射机制的比较

原生反射

  C#通过System.Reflection程序集提供出了强大完整的反射功能,使我们可以在程序运行期获得“程序集”、“模块”、“类型”等信息,同时她也提供出了一种通用的方式的来访问与使用这些信息。于是我们在代码的世界中,面对不同的“人”或“物”,就有了不卑不亢的同一种腔调。
        在这里我们只讨论函数调用,后面也只以函数调用的角度来比较一下各个反射机制的性能。
        在原生反射的框架下进行函数调用有两种较为常用的“招式”。分别如下:

        1. 通过MethodInfo
            以函数方法对象抽象调用函数,调用效率较低。
/// <summary>
    /// 原生反射测试
    /// </summary>
    public class NativeReflectTest
    {
        /// <summary>
        /// 运行
        /// </summary>
        public static void Run()
        {
            //类型对象
            Type personType = typeof(Person);
            
            //方法信息
            MethodInfo methodInfo = personType.GetMethod("Say");
 
            //对象与参数
            Person person = new Person();
            String word = "";
            Object[] param = new Object[] { word, 0 };
 
            //极大次数调用测试运行时间
            Profiler.Start();
            for (int i = 0; i < 1000000; i++)
            {
                param[1] = i;
                methodInfo.Invoke(person, param);
            }
            Profiler.StopAndPrint("1000000 times invoked by Reflection: ");
        }
    }
2. 通过Assembly
            用Assembly生成直接的对象,然后调用期则等同于直接调用函数。

/// <summary>
    /// 程序集测试
    /// </summary>
    public class AssemblyTest
    {
        /// <summary>
        /// 运行
        /// </summary>
        public static void Run()
        {
            Assembly assembly = Assembly.Load("FastMethodInvoker");
            Person person = assembly.CreateInstance("FastMethodInvoker.example.subject.Person") as Person;
 
            String word = "";
 
            Profiler.Start();
            for (int i = 0; i < 1000000; ++i)
            {
                person.Say(ref word, i);
            }
            Profiler.StopAndPrint("1000000 times invoked by Assembly: ");
        }
    }
委托(delegate)

其实代理本身与反射没有什么直接的关系,只是因为我们讨论的是函数调用,而委托天生就流着函数调用的血脉。
        相对于原生反射,委托显得更加特例化一些,他需要为每种不同的形式的函数预先定义出委托的类型,然后可以在不同的类的函数上进行绑定。委托比原生反射的抽象抽象程度弱化了一些。
         绑定委托的“招式”如下:
public delegate void SayHandle(ref String word, int count);
 
    /// <summary>
    /// 代理测试
    /// </summary>
    public class DelegateTest
    {
        /// <summary>
        /// 运行
        /// </summary>
        public static void Run()
        {
            Type type = typeof(Person);
 
            MethodInfo methodInfo = type.GetMethod("Say");
 
            Person person = new Person();
            String word = "";
            SayHandle delegateObject = Delegate.CreateDelegate(typeof(SayHandle), person, methodInfo) as SayHandle;
 
            Profiler.Start();
            for (int i = 0; i < 1000000; i++)
            {
                delegateObject(ref word, i);
            }
            Profiler.StopAndPrint("1000000 times invoked by delegate: ");
        }
    }
快速调用(fast invoke)

  在codeproject 上介绍了一种FastInvoke方法来进行函数反射。相对于原生反射,她提供了一种更底层的方式来实现。主要是MSIL语言来创建指令流,以达到调用期与平常代码相同的执行效率。
         MSIL语言被称为Microsoft中间语言,主要用来做跨平台支持,C#将MSIL代码生成到当前机器的机器码。在FastInvoke中,直接生成调用函数的MSIL代码,则可以等同于编写C#直接调用函数的代码。
         在小鱼酱包装后的接口中,FastInvoke方法的“招式”如下:
/// <summary>
    /// 快速调用测试
    /// </summary>
    public class FastInvokeTest
    {
        /// <summary>
        /// 运行
        /// </summary>
        public static void Run()
        {
            //快速调用句柄
            FastInvokeHandler fastInvoker = FastInvoker.CreateHandler<Person>("Say");
 
            //对象与参数
            Person person = new Person();
            String word = "";
            Object[] param = new Object[] { word, 0 };
 
            //极大次数调用测试运行时间
            Profiler.Start();
            for (int i = 0; i < 1000000; i++)
            {
                param[1] = i;
                fastInvoker(person, param);
            }
            Profiler.StopAndPrint("1000000 times invoked by FastInvoke: ");
        }
    }
这里是源代码地址:A General Fast Method Invoker - CodeProject
这里是小鱼酱整理后的代码地址:FastMethodInvoker.zip_免费高速下载|百度网盘-分享无限制

性能比较

下面是几种反射调用的一个实验,分别调用一个简单函数极大次数(一百万次),如下:

class Program
    {
        static void Main(string[] args)
        {
            //经典反射测试
            NativeReflectTest.Run();
 
            //快速调用测试
            FastInvokeTest.Run();
 
            //程序集
            AssemblyTest.Run();
 
            //代理
            DelegateTest.Run();
 
            //直接调用测试
            DirectInvokeTest.Run();
 
            Console.ReadLine();
        }
    }

性能结果:

      结论为,原生调用的时间消耗与直接调用相比较差别巨大;而Assembly需要先通过反射构建出对象,然后再通过直接调用的方式访问函数,构建对象的性能效率没有统计,如果加入统计过程中,Assembly方法的性能会比原生调用还要低,同时Assembly方法破坏了反射需要的统一抽象。delegate方法其实就是直接调用,但是与Assembly相同的是他同样也破坏了反射需要的统一抽象。而FastInvoke与直接调用性能相差不多,并且保持了统一形式进行访问的特性。
这里是性能比较的项目地址:FastMethodInvoker.zip_免费高速下载|百度网盘-分享无限制

//

Assembly asm = Assembly.GetAssembly(typeof(我的类));

System.Type type = asm.GetType("我的类名字");

var method = type.GetMethod("我的函数名字");

Type.GetType("my type name" + ", Assembly-CSharp");

MethodInfo instance = my type name.GetMethod("GetInstance", BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);

var objTempIns = instance.Invoke(null, null);

Type instTempType = objTempIns .GetType();

MethodInfo myfuc = instTempType .GetMethod("我的函数", BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);

method.Invoke(objTempIns , null);

var inst = my type name.GetProperty("Instance", BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static); // 这个 inst 为 null

var temfieldInfo = my type name.GetField("Instance", BindingFlags.Public | BindingFlags.Static);

var temmethod = my type name.GetMethod("我的函数", BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static); temmethod .Invoke(temfieldInfo .GetValue(null), null);

public static 我的类 Instance = null;

public static 我的类 GetInstance()

{

return Instance;

}

private void Awake()

{

Instance = this;

}

//

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值