• 理解C#反射机制

    2016-11-01 13:12:28
    反射是.NET中的重要机制,通过反射可以得到*.exe或*.dll等程序集内部的接口、类、方法、字段、属性、特性等信息,还可以动态创建出类型实例并执行其中的方法。

    反射是.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#反射详解

    2018-02-01 15:49:54
    可以使用反射动态创建类型的实例,将类型绑定到现有对象,或从现有对象获取类型并调用其方法或访问其字段和属性。如果代码中使用了特性,可以利用反射对它们进行访问。【MSDN】 使用场景 需要访问程序元数据

    原文链接:https://www.cnblogs.com/Stephenchao/p/4481995.html

    反射定义

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

    使用场景

    • 需要访问程序元数据的特性。
    • 检查和实例化程序集中的类型。
    • 在运行时构建新类型。使用System.Reflection.Emit中的类。
    • 执行后期绑定,访问在运行时创建的类型的方法。【MSDN】

    形象说明

      地球的内部结构:地球的内部结构大体可以分为三层:地壳、地幔和地核。地壳是固体,地核是液体,地幔则是半液半固的结构(地理知识)。如何在地球表面不用深入地球内部就知道其内部结构呢?答案是:向地球发射“地震波”。地震波分两种,一种是横波,另一种是纵波。横波只能穿透固体,而纵波既可以穿透固体又可以穿透液体。通过在地面对纵波和横波的返回情况,我们就可以大体断定地球内部的构造了。

      B型超声波:大家体检的时候都做过B超吧,B超可以透过肚皮探测到你的内脏的生理情况。这是如何做到的呢?答案是:它可以透过肚皮向你体内发射B型超声波,当超声波遇到内脏壁的时候就会产生一定的“回音”反射,然后把“回音”进行处理就可以显示出你的内脏的情况了。(部分细节不予追究)

      大家注意到这两个例子的共同特点,就是从一个对象的外部去了解对象内部的构造,而且都是利用了波的反射功能。在.NET中的反射也可以实现从对象的外部来了解对象(或程序集)内部结构的功能,哪怕你不知道这个对象(或程序集)是什么,另外.NET中的反射还可以动态创建出对象并执行它其中的方法。

      反射是.NET中重要的机制,通过反射,可以在运行时获得程序或程序集中每一个类型(包括类、结构、委托、接口和枚举等)的成员和成员的信息。有了反射,即可对每一个类型了如指掌。另外我还可以直接创建对象,即使这个对象的类型在编译时还不知道。

    反射的用途

    (1)使用Assembly定义和加载程序集,加载在程序集中的所有模块以及从此程序集中查找类型并创建该类型的实例。
    (2)使用Module了解包含模块的程序集以及模块中的类等,还可以获取在模块上定义的所有全局方法或其他特定的非全局方法。
    (3)使用ConstructorInfo了解构造函数的名称、参数、访问修饰符(如pulic 或private)和实现详细信息(如abstract或virtual)等。
    (4)使用MethodInfo了解方法的名称、返回类型、参数、访问修饰符(如pulic 或private)和实现详细信息(如abstract或virtual)等。
    (5)使用FiedInfo了解字段的名称、访问修饰符(如public或private)和实现详细信息(如static)等,并获取或设置字段值。
    (6)使用EventInfo了解事件的名称、事件处理程序数据类型、自定义属性、声明类型和反射类型等,添加或移除事件处理程序。
    (7)使用PropertyInfo了解属性的名称、数据类型、声明类型、反射类型和只读或可写状态等,获取或设置属性值。
    (8)使用ParameterInfo了解参数的名称、数据类型、是输入参数还是输出参数,以及参数在方法签名中的位置等。

    反射用到的命名空间

    System.Reflection
    System.Type
    System.Reflection.Assembly

    反射用到的主要类

    System.Type 类--通过这个类可以访问任何给定数据类型的信息。
    System.Reflection.Assembly 类--它可以用于访问给定程序集的信息,或者把这个程序集加载到程序中。

    System.Type类用法

      System.Type类对于反射起着核心的作用。但它是一个抽象的基类,Type有与每种数据类型对应的派生类,我们使用这个派生类的对象的方法、字段、属性来查找有关该类型的所有信息。获取给定类型的Type引用有3种常用方式:

    1、使用 C# typeof 运算符

    Type t = typeof(string);

    2、 使用对象GetType()方法

    string s = "grayworm";
    Type t = s.GetType(); 

    3、还可以调用Type类的静态方法GetType()

    Type t = Type.GetType("System.String");

    Type类的属性

    • Name数据类型名
    • FullName 数据类型的完全限定名(包括命名空间名)
    • Namespace 定义数据类型的命名空间名
    • IsAbstract 指示该类型是否是抽象类型
    • IsArray 指示该类型是否是数组
    • IsClass 指示该类型是否是类
    • IsEnum 指示该类型是否是枚举
    • IsInterface 指示该类型是否是接口
    • IsPublic 指示该类型是否是公有的
    • IsSealed 指示该类型是否是密封类
    • IsValueType 指示该类型是否是值类型

    Type类的方法

    • GetConstructor(), GetConstructors():返回ConstructorInfo类型,用于取得该类的构造函数的信息
    • GetEvent(), GetEvents():返回EventInfo类型,用于取得该类的事件的信息
    • GetField(), GetFields():返回FieldInfo类型,用于取得该类的字段(成员变量)的信息
    • GetInterface(), GetInterfaces():返回InterfaceInfo类型,用于取得该类实现的接口的信息
    • GetMember(), GetMembers():返回MemberInfo类型,用于取得该类的所有成员的信息
    • GetMethod(), GetMethods():返回MethodInfo类型,用于取得该类的方法的信息
    • GetProperty(), GetProperties():返回PropertyInfo类型,用于取得该类的属性的信息

    我们可以调用这些成员,其方式是调用Type的InvokeMember()方法,或者调用MethodInfo, PropertyInfo和其他类的Invoke()方法。

    实例应用

    //实例类
    class ReflectionClass
    {
        public int id;
    
        private string name;
        /// <summary>
        /// 姓名
        /// </summary>
        public string Name
        {
            get { return name; }
            set { name = value; }
        }
        private string age;
        /// <summary>
        /// 年龄
        /// </summary>
        public string Age
        {
            get { return age; }
            set { age = value; }
        }
        private string sex;
        /// <summary>
        /// 性别
        /// </summary>
        public string Sex
        {
            get { return sex; }
            set { sex = value; }
        }
    
        public ReflectionClass(string name, string age)
        {
            this.name = name;
            this.age = age;
        }
        public ReflectionClass(string sex)
        {
            this.sex = sex;
        }
        public ReflectionClass()
        { }
    
        public void Show()
        {
            Console.WriteLine("姓名:" + name + "\n" + "年龄:" + age + "\n" + "性别:" + sex);
        }
    }

    1、查看类中的构造方法

    ReflectionClass rc = new ReflectionClass();
    Type t = rc.GetType();
    ConstructorInfo[] ciArray = t.GetConstructors(); //获取类的所有构造函数
    foreach (ConstructorInfo ci in ciArray)
    {
        ParameterInfo[] piArray = ci.GetParameters(); //取出每个构造函数的所有参数
        foreach (ParameterInfo pi in piArray)
        {
            Console.WriteLine(pi.ParameterType.ToString()+"\n"+pi.Name+"\n");
        }
    }

    打印结果:

    这里写图片描述
    图1-1 查看类中的构造方法

    2、用构造函数动态生成对象

    Type t = typeof(ReflectionClass);
    Type[] pt = new Type[2];
    pt[0]=typeof(string);
    pt[1]=typeof(string);
    //根据参数类型获取构造函数
    ConstructorInfo ci = t.GetConstructor(pt);
    //构造Object数组,作为构造函数的输入参数
    object[] obj = new object[2] {"zhangsan","23"};
    //调用构造函数生成对象
    object o = ci.Invoke(obj);
    //调用生成的对象的方法测试是否对象生成成功
    ((ReflectionClass)o).Show();

    打印结果:

    这里写图片描述
    图1-2 用构造函数动态生成对象

    3、用Activator生成对象

    Type t = typeof(ReflectionClass);
    object[] obj = new object[2] {"zhangsan","23"};
    //用Activator的CreateInstance静态方法,生成新对象
    object o = Activator.CreateInstance(t, obj);
    ((ReflectionClass)o).Show();

    打印结果:

    这里写图片描述
    图1-3 用Activator生成对象

    4、查看类中的属性

    ReflectionClass rc = new ReflectionClass();
    Type t = rc.GetType();
    PropertyInfo[] piArray = t.GetProperties();
    foreach (PropertyInfo pi in piArray)
    {
        Console.WriteLine(pi.Name);
    }

    打印结果:

    这里写图片描述
    图1-4 查看类中的属性

    5、查看类中的public方法

    ReflectionClass rc = new ReflectionClass();
    Type t = rc.GetType();
    MethodInfo[] mi = t.GetMethods();
    foreach (MethodInfo method in mi)
    {
        Console.WriteLine(method.ReturnType + "\n" + method.Name);
    }

    打印结果:

    这里写图片描述
    图1-5 查看类中的public方法

    6、查看类中的public字段

    ReflectionClass rc = new ReflectionClass();
    Type t = rc.GetType();
    FieldInfo[] fi = t.GetFields();
    foreach (FieldInfo fieldInfo in fi)
    {
        Console.WriteLine(fieldInfo.Name);
    }

    打印结果:

    这里写图片描述
    图1-6 查看类中public字段

    7、用反射生成对象,并调用属性、方法和字段进行操作

    ReflectionClass rc = new ReflectionClass();
    Type t = rc.GetType();
    object obj = Activator.CreateInstance(t);
    //取得ID字段
    FieldInfo fi = t.GetField("id");
    //给ID字段赋值
    fi.SetValue(obj, 2);
    //取得Name属性
    PropertyInfo piName = t.GetProperty("Name");
    //给Name属性赋值
    piName.SetValue(obj, "jujianfei", null);
    PropertyInfo piAge = t.GetProperty("Age");
    piAge.SetValue(obj, "23", null);
    //取得Show方法
    MethodInfo mi = t.GetMethod("Show");
    //调用Show方法
    mi.Invoke(obj, null);
    Console.WriteLine("ID为:" + ((ReflectionClass)obj).id);

    打印结果:

    这里写图片描述
    图1-7 综合应用

    System.Reflection.Assembly类的用法

      Assembly类可以获得程序集的信息,也可以动态的加载程序集,以及在程序集中查找类型信息,并创建该类型的实例。使用Assembly类可以降低程序集之间的耦合性,有利于软件结构的合理化。
    1、通过程序集名称返回Assembly对象

    Assembly assembly = Assembly.Load("ReflectionDemo2");

    2、通过DLL文件名称返回Assembly对象

    Assembly assembly = Assembly.LoadFrom("ReflectionDemo2.dll");

    3、通过Assembly获取程序集中类

    Type t = assembly.GetType("ReflectionDemo2.ReflectionClass"); //参数必须是类的全名

    4、通过Assembly获取程序集中所有的类

    Type[] tArray = assembly.GetTypes(); 

    5、通过程序集的名称反射

    Assembly assembly = Assembly.Load("ReflectionDemo2");
    Type t = assembly.GetType("ReflectionDemo2.ReflectionClass"); //参数必须是类的全名
    object o = Activator.CreateInstance(t,"男");
    MethodInfo mi = t.GetMethod("Show");
    mi.Invoke(o,null);

    打印结果:

    这里写图片描述
    图1-8 通过程序集的名称反射

    6、通过DLL文件全名反射其中的所有类型

    Assembly assembly = Assembly.LoadFrom("ReflectionDemo2.dll");
    Type[] tArray = assembly.GetTypes();
    foreach (Type t in tArray)
    {
        if (t.FullName == "a.b.c")
        {
            object o = Activator.CreateInstance(t);
        }
    }

    总结

      上面的例子,都是对类中public修饰的成员的操作,实际上private和protected修饰的成员也可以访问到,详情请看:C#之玩转反射,这里不再做具体的探索。

    展开全文
  • C#反射

    2019-10-24 15:40:07
    1. 过多使用,会造成逻辑模糊,因为反射已经绕过的源码,看不到逻辑实现,会造成后期维护上的困扰 2. 性能的问题,使用反射处在解释的操作,主要应用在对灵活性和拓展性要求很高的系统框架上,普通程序不建议使用 ...

    优点:

    1.    提高程序的灵活性与可扩展性,耦合度;

    缺点:

    1.    过多使用,会造成逻辑模糊,因为反射已经绕过的源码,看不到逻辑实现,造成后期维护上的困扰

    2.       性能的问题,使用反射处在解释的操作,主要应用在对灵活性和拓展性要求很高的系统框架上,普通程序不建议使用

    小结:.Net应用程序由几个部分:‘程序集(Assembly)’、‘模块(Module)’、‘类型(class)’组成

     更简单的说反射是为了动态地运行时加载,而静态代码是在编译时就确定好了。也就是说当你的程序需要在运行时再做一些晚绑定,动态加载或检查对象等操作时,你就需要用到反射

    以下为实例TestDemo:

    新增类 Test.cs 里面有两个class 为 Test && Man  方便之后做测试;

    Class Test 定义有 字符串 MyType,类Man,Man中含有 定义的三个字符串分别是:Name,Age,sex ;还有一个返回String类型的方法Init();

     

    二:从调试模式看结果

    在类工厂中动态创建类的实例,使用System.Activator.CreateInstance,方法入参为两个string类型,分别入参 “类库名称” 和 “类名”这样就能将Test.cs实例出来啦!

    实例出来后,我们获取到了 Test.cs中的Mytpe &&man,但是他们都是null的;

    *SetValue()给实例出来的MyType赋值"I'm so cool"

    *GetValue()获取值

    *GetProperty() 搜索指定名称的公共属性;

     

    用objstr接收到值

     

    相对的用法:在类Man中看结果:
    一样的用法,可以看到效果也是大同小异的,最终取到Man的赋值;

    三:调用方法

    前面在Test.cs中定义了一个public 公开的Init()方法,该方法实现的是一个简单的字符串拼接,入参为两个string: str1 and str2

     

    现在我要在 static void Main 中 用反射去赋值并输出

    打开文本可视化工具:可以看到已经绕过类,直接入参调用Init()的方法返回了字符串拼接后的结果 “yi ya yi ya yook ok ok ”

    Invoke()传入,string[]数组,包含两个string类型的值;

    GetMehtod()搜索具有指定名称的公共方法;

    以上只是反射中的冰山一角,还有调用dll,各种各样的方式......

    作为.Net中较为重要的机制,有了反射我们就可以得到.net中每一个类型的相关信息,简单的来说就是通过反射获取成员变量。它的一些方法,属性,时间,构造函数以及参数等等。如果获得了构造函数的信息,即可直接创建对象,即使这个对象的类型在编译时还不知道。程序代码在编译后生成可执行的应用,我们首先要了解这种可执行应用程序的结构。

    也是突然心血来潮,前面写了那么多的JAVA基础的学习总结以后。想到假期写了两篇C#的技术点总结。

    对反射我也不是了解多少,都是结合自己在慕课学习和之前有了解的一些知识而言总结的,所以可以说都是些自己总结的表层的基础东西。

    展开全文
  • C#反射机制

    2019-03-26 16:05:19
    四十五:反射的实现原理? 审查元数据并收集关于它的类型信息的能力。实现原理:在运行时根据程序集及其中的类型得到元数据。下面是实现步骤: 1. 导入using System.Reflection; 2. Assembly.Load(“程序集”)...

    四十五:反射的实现原理?

    审查元数据并收集关于它的类型信息的能力。实现原理:在运行时根据程序集及其中的类型得到元数据。下面是实现步骤:

    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,方法参数);

    https://blog.csdn.net/xiaouncle/article/details/52983924

    反射是.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);
        }
    }

    https://blog.csdn.net/danteshenqu/article/details/80767606

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

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

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

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

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

    https://blog.csdn.net/Yuan_bowen/article/details/80493540

     

    目录:

    一. 反射的主要特性

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

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

        2)当已经获得对象后通过对象的GetType()方法来获取指定对象的类型的Type对象

      2.获取Person类中的所有的方法

      3.获取某个类型的所有属性

      4.获取类中的所有字段,私有字段无法获取

      5.获取所有成员,不包含私有成员

    二. 反射动态加载程序集

      1.动态加载一个程序集

      2.获取刚刚加载的程序集中的所有的类型

        1)GetTypes()获取了所有的类型

        2)只获取那些public的类型

      3.获取程序集中某个类的Type

      4.动态调用类的方法

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

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

          1> 调用不带重载的方法

          2>调用带重载的方法

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

        1)获取Name属性

        2)为属性赋值

        3) 获取属性值

        4)获取方法并调用

      6.手动查找类型的构造函数,并且调用该构造函数来创建类型的对象

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

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

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

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

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

    ————————————————————————————————————————————————————————————————————————————

     

    反射是什么?

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

    一. 反射的主要特性

    在介绍反射的主要特性之前我们先建一个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++)
    {
    Console.WriteLine(methods[i].Name);
    }

     

    3.获取某个类型的所有属性
    PropertyInfo[] properties = personType.GetProperties();
    for (int i = 0; i < properties.Length; i++)
    {
    Console.WriteLine(properties[i].Name);
    }
    Console.ReadKey();


    4.获取类中的所有字段,私有字段无法获取
    FieldInfo[] fields = personType.GetFields();
    for (int i = 0; i < fields.Length; i++)
    {
    Console.WriteLine(fields[i].Name);
    }
    Console.ReadKey();


    5.获取所有成员,不包含私有成员
    MemberInfo[] members = personType.GetMembers();
    for (int i = 0; i < members.Length; i++)
    {
    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++)
    {
    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();

    【C#】:浅谈反射机制https://blog.csdn.net/lianjiangwei/article/details/47207875

    什么是反射?

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

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

            

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

            为什么用反射?

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

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

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

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

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

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

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

            怎么用反射?

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

            首先我们先写一个目标类Student     

    <span style="font-size:18px;">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 +"岁了!");
            }
        }
    }</span>
            然后我们在控制台应用程序中去利用反射操纵这个类 

    <span style="font-size:18px;">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();
            }
        }
    }</span>
            小结一下:对于反射这个概念,一开始我是比较模糊的,虽然很多次的听到别人在说在讲,但是由于没有自己去查资料去研究,去动手代码实现,终究不能感同身受,理解其中的原理和思想,如今阅读了大量的博客和文章之后,又动手实践了一下,有了一些浅浅的理解,由于Donet的反射机制是封装好的,所以对于反射内部实现原理还不清楚,期待以后能够继续深入学习。

    https://blog.csdn.net/llgood806/article/details/43890711

    1. 前言

            反射是一项很有趣的技术,她提供了另一个视角来模糊、统一地看待我们用代码搭建起来的小世界。由于之前工作的关系,小鱼酱曾用C++初略地实现过一套反射系统,用来支持游戏中属性编辑器的开发,在C++中反射是一项注入式或者后生成的一种编程方式,会导致代码难以阅读,脱离语言的美感。但在C#中的反射却是自然而优雅。
            因为最近在做手游开发的缘故,开始研究unity3D,开始重拾久违的C#。于是下面小鱼酱将简单介绍一下C#中的反射技术,并通过函数调用的角度来比较一下各个方式的性能。

    2. 几种反射机制

    2.1. 原生反射

            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: ");
            }
        }

     

     

    2.2. 委托(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: ");
            }
        }

     

     

    2.3. 快速调用(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: ");
            }
        }

     


             这里是源代码地址:http://www.codeproject.com/Articles/14593/A-General-Fast-Method-Invoker
             这里是小鱼酱整理后的代码地址:http://pan.baidu.com/s/1hqAajuG

     

    3. 性能比较

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

           

        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与直接调用性能相差不多,并且保持了统一形式进行访问的特性。

     

     

    这里是性能比较的项目地址:http://pan.baidu.com/s/1hqAajuG
     

    展开全文
  • 今天接触到了一个新词,就是反射,当我看到反射这个词的时候我不知道这个是什么东西。于是乎就问老人,老人给我说可以参看一个方法就是GetTipy()方法,但是这个到底是什么东西...但是对于C#中来说反射也是一样的一个道

    今天接触到了一个新词,就是反射,当我看到反射这个词的时候我不知道这个是什么东西。于是乎就问老人,老人给我说可以参看一个方法就是GetTipy()方法,但是这个到底是什么东西呢,通过我查找的资料我这里发表一下我自己的小小的理解吧。


    一、什么是反射

        当然对于反射这个词来说,我们并不是很陌生,比如说镜子可以反射,B超也是利用反射的原理进行成像的。但是对于C#中来说反射也是一样的一个道理,反射是C#中的重要机制,通过反射,可以在运行时获得程序或程序集中每一个类型(包括类、结构、委托、接口和枚举等)的成员和成员的信息。有了反射,即可对每一个类型了如指掌。另外我还可以直接创建对象,即使这个对象的类型在编译时还不知道。 

        不知道通过上面你的讲述是否有人能够理解,比如说,给我们变量,这个变量可以使int,也可以是String或者其他的类,但是当前之下我们并不是很了解这个变量,不仅知道这个变量是什么类型的,如果这个是一个类,我们不知道这个类中有哪些方法,但是通过反射我们就可以得到这些东西。


    二、反射有什么用途

        我想通过上面的讲解,应该对反射是什么了解了吧。但是反射的用途具体有哪些呢,下面给大家举一些例子:

        1、使用Assembly定义和加载程序集,加载在程序集清单中列出模块,以及从此程序集中查找类型并创建该类型的实例。

        2、使用Module了解包含模块的程序集以及模块中的类等,还可以获取在模块上定义的所有全局方法或其他特定的非全局方法。

        3、使用ConstructorInfo了解构造函数的名称、参数、访问修饰符(如pulic 或private)和实现详细信息(如abstract或virtual)等。

        4、使用MethodInfo了解方法的名称、返回类型、参数、访问修饰符(如pulic 或private)和实现详细信息(如abstract或virtual)等。

        5、使用FiedInfo了解字段的名称、访问修饰符(如public或private)和实现详细信息(如static)等,并获取或设置字段值。

        6、使用EventInfo了解事件的名称、事件处理程序数据类型、自定义属性、声明类型和反射类型等,添加或移除事件处理程序。

        7、使用PropertyInfo了解属性的名称、数据类型、声明类型、反射类型和只读或可写状态等,获取或设置属性值。

        8、使用ParameterInfo了解参数的名称、数据类型、是输入参数还是输出参数,以及参数在方法签名中的位置等。


    三、反射所要用到的命名空间

        在C#中要使用反射,应该引用哪些明明空间呢?其实使用的也不是很多,就仅仅那么三个:  System.Reflection、System.Type、 System.Reflection.Assembly。其实这三个命名空间各有各的用处,但是主要用的也就  System.Type 类--通过这个类可以访问任何给定数据类型的信息;System.Reflection.Assembly类--它可以用于访问给定程序集的信息,或者把这个程序集加载到程序中。下面我们介绍一个那个叫做System.Type的命名空间吧

    System.Type 类对于反射起着核心的作用。但它是一个抽象的基类,Type有与每种数据类型对应的派生类,我们使用这个派生类的对象的方法、字段、属性来查找有关该类型的所有信息。

        其实获取给定数据的类型有三种表示方法

        String str = "caosiyuan";

        (1)  Type t = typeof(str); 或者是Type t = typeof(String);

        (2)  Type t = str.GetType();

        (3)  Type T = Type.GetType(str); 或者是 Type t = Type.GetType(String);

        上面的三种方法都能够获得String类型,但是接下来应该怎么去做呢,比如说要获取里面的方法的名字呢?

                string n = "grayworm";
                 Type t = n.GetType();
                 foreach (MemberInfo mi in t.GetMembers())
                 {
                     Console.WriteLine("{0}/t{1}",mi.MemberType,mi.Name);
                 }

       通过这些方法可以获得一个类中的所提供的方法。


       Type的属性

          Name 数据类型名

          FullName 数据类型的完全限定名(包括命名空间名)

          Namespace 定义数据类型的命名空间名

          IsAbstract 指示该类型是否是抽象类型

          IsArray   指示该类型是否是数组

          IsEnum   指示该类型是否是枚举

          IsClass   指示该类型是否是类

          IsInterface    指示该类型是否是接口

          IsPublic 指示该类型是否是公有的

          IsSealed 指示该类型是否是密封类

          IsValueType 指示该类型是否是值类型

       Type的方法

             GetConstructor(), GetConstructors():返回ConstructorInfo类型,用于取得该类的构造函数的信息
            GetEvent(), GetEvents():返回EventInfo类型,用于取得该类的事件的信息
            GetField(), GetFields():返回FieldInfo类型,用于取得该类的字段(成员变量)的信息
            GetInterface(), GetInterfaces():返回InterfaceInfo类型,用于取得该类实现的接口的信息
            GetMember(), GetMembers():返回MemberInfo类型,用于取得该类的所有成员的信息
            GetMethod(), GetMethods():返回MethodInfo类型,用于取得该类的方法的信息
            GetProperty(), GetProperties():返回PropertyInfo类型,用于取得该类的属性的信息
        可以调用这些成员,其方式是调用Type的InvokeMember()方法,或者调用MethodInfo, PropertyInfo和其他类的Invoke()方法。

       

        


    
    展开全文
  • C#反射破坏单例

    2019-07-20 12:40:10
    上文我们讲到了反射的基本操作,实例化对象、属性、方法、特性等操作,可以参考C#反射 咱们切入正题,单例有两种,一种是程序加载时创建,一种是使用时创建,我们这里主要是创建一个加载时创建的单例。我们...
  • C#反射(Reflection) 反射指程序可以访问、检测和修改它本身状态或行为的一种能力。 程序集包含模块,而模块包含类型,类型又包含成员。反射则提供了封装程序集、模块和类型的对象。 您可以使用反射动态地创建...
  • 转载自:C#反射实现简单的插件系统如果用过一些优秀的开源或是非开源的应用软件,就会发现这些软件的一个很大的优势就是其开放性,任何有能力的人都可以为其开发不同的插件来增强其的功能。比如著名的foobar2000,...
  • C#反射机制-附Demo学习

    2018-08-24 10:23:19
    一、C#反射机制 反射是.NET中的重要机制,通过反射,可以在运行时获得程序或程序集中每一个类型(包括类、结构、委托、接口和枚举等)的成员和成员的信息。有了反射,即可对每一个类型了如指掌。另外我还可以直接创建...
  • C# 反射实例代码 接口方式动态加载dll方式
  • C# 反射调用私有事件

    2019-08-30 08:53:43
    C# 反射调用私有事件经常会不知道如何写,本文告诉大家如何调用
  • C#反射命名空间浅析

    2010-12-16 17:41:00
    我们在了解C#反射之后,那么在掌握C#反射命名空间的时候需要注意什么呢?那么本文就向你介绍这些内容。 学习C#反射命名空间之前我们来看看C#反射的概念,反射是一个运行库类型发现的过程。 通过反射可以得到...
  • C# 反射

    2019-03-02 15:42:48
    实验四:C#反射 具体要求 构建一个components.txt文件,每行代表一个类(比如形状类Shape)的名字(这些类可以来自系统库,或者自己构造);程序逐行扫描该文件,构建对应的类的对象。要求: 并把这些对象放到数组...
  • 是一个 关于c#反射的几乎最好最全面的例子。
  • C#反射方法:程序集反射、类型反射、接口反射、类型成员反射   反射(原创推荐)  在程序中,当我们需要动态的去加载程序集的时候(将对程序集的引用由编译时推移到运行时),反射是一种很好的选择。反射为...
  • C#反射加壳实例:对编译出来的C# exe程序进行反射加壳,原来是利用反射来加壳(复制程序到项目文件中,并设置成为“嵌入式资源”)。由于是利用控制台程序对原exe进程反射加壳,控制台程序启动后有黑屏的控制台窗口...
  • c#反射 通过类名获取实例和属性,方法 ** 元数据 程序是用来处理数据的,文本和特性都是数据,而我们程序本身(类的定义和BLC中的类)这些也是数据;有关程序及其类型的数据被称为元数据(metadata),它们保存在...
  • C#反射(Reflection)详解

    2020-05-18 16:25:15
    C#反射(Reflection)详解 什么是反射 命名空间和装配体的关系
  • C#反射和特性

    2015-09-28 18:05:32
    C#反射和特性 1、Type类 预定义类型(int long和string等),BCL中的类型(Console,IEnumerable等)和程序员自定义类型(MyClass,MyDel等)。 每种类型都有自己的成员和特性。 BCL声明了一个叫做Type的抽象类,它被设计...
  • c# 简单的IOC实现框架,包含通过配置,利用c#反射机制来动态注入
1 2 3 4 5 ... 20
收藏数 47,053
精华内容 18,821