• .net反射


    最简单,随便给你一个dll文件   你可以通过反射来获取它里面的的类,方法,属性,等等

    反射中查询里面包含的方法和属性

    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net.Mail;
    using System.Text;
    using System.Text.RegularExpressions;
    using System.Threading.Tasks;
    using System.Reflection;

    namespace ConsoleApplication5
    {

        class MyClass
        {
            int x;
            int y;
            public MyClass(int i, int j)
            {
                x = i;
                y = j;
            }
            public int sum()
            {
                return x + y;
            }
            public bool IsBetween(int i)
            {
                if (x < i && i < y) return true;
                else return false;
            }
            public void Set(int a, int b)
            {
                x = a;
                y = b;
            }
            public void Set(double a, double b)
            {
                x = (int)a;
                y = (int)b;
            }
            public void Show()
            {
                Console.WriteLine("x:{0},y:{1}", x, y);
            }
        }
        class ReflectDemo
        {
            static void Main(string[] args)
            {
                Type t = typeof(MyClass);   //获取描述MyClass类型的Type对象
                Console.WriteLine("Analyzing methods in " + t.Name);  //t.Name="MyClass"

                MethodInfo[] mi = t.GetMethods();  //MethodInfo对象在System.Reflection命名空间下。
                foreach (MethodInfo m in mi) //遍历mi对象数组
                {
                    Console.Write(m.ReturnType.Name); //返回方法的返回类型
                    Console.Write(" " + m.Name + "("); //返回方法的名称

                    ParameterInfo[] pi = m.GetParameters();  //获取方法参数列表并保存在ParameterInfo对象数组中
                    for (int i = 0; i < pi.Length; i++)
                    {
                        Console.Write(pi[i].ParameterType.Name); //方法的参数类型名称
                        Console.Write(" " + pi[i].Name);  // 方法的参数名
                        if (i + 1 < pi.Length)
                        {
                            Console.Write(", ");
                        }
                    }
                    Console.Write(")");
                    Console.WriteLine(); //换行
                }
                Console.ReadKey();
            }
        }
    }

    这个例子是使用反射的简单例子

    using System;
    using System.Collections.Generic;
    using System.Text;
    namespace AssemblyDemo
    {
        public class Person
        {
            private int age;
            private string name;
            public Person()
            {
                age = 20;
                name = "未知";
            }
            public Person(int age, string name)
            {
                this.age = age;
                this.name = name;
            }
            public override string ToString()
            {
                return String.Format("姓名={0},年龄={1}", name, age);
            }
        }
    }

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Reflection;//注意要添加这个命名控件的引用
    namespace AssemblyDemo
    {
        public class Program
        {
            public static void Main(string[] args)
            {
                Assembly asm=Assembly.Load("AssemblyDemo");
                Type pt = asm.GetType("AssemblyDemo.Person");//注意这里用全路径AssemblyDemo.Person而不是Person
                Person p =(Person) Activator.CreateInstance(pt);//创建不带参数的实例
                Console.WriteLine(p.ToString());
               
                Person p2 = (Person)Activator.CreateInstance(pt,30,"zhoufoxcn");//创建带参数的实例
                Console.WriteLine(p2.ToString());
                Console.ReadLine();
            }
        }
    }

    运行结果是:

    姓名=未知,年龄=20 

    姓名=zhoufoxcn,年龄=30

    本节中,我将通过具体的实例。教大家如何在)C#).NET开发中使用反射。

    首先,我新建一个普通的类库项目。在该项目的测试类中,定义好 属性、静态方法、实例方法、无参方法等... 代码如下:

    using System; 

    using System.Collections.Generic; 

    using System.Linq; 

    using System.Text; 

    namespace ReflectorTest 

        class Test 

        { 

            private string name; 

            public string Name { get; set; } 

            /// <summary> 

            /// 静态方法 

            /// </summary> 

            /// <returns></returns> 

            public static string staticMethod(string  name) 

            { 

                return name; 

            } 

            /// <summary> 

            /// 实例方法 

            /// </summary> 

            /// <param name="name"></param> 

            /// <returns></returns> 

            public string sayHello(string name)  

            { 

                return "hello:" + name; 

            } 

            /// <summary> 

            /// 无参的方法 

            /// </summary> 

            /// <returns></returns> 

            public string noParm()  

            { 

                return "I'M  A noParm Method"; 

            } 

        } 

    上面的类库项目,编译通过后,会生成一个DLL文件。好的,我们就是要通过“反射”技术,来尝试着看看这个DLL里面包含的相关元素信息,做一些模拟的操作等。

    有点类似于“反编译”吧?呵呵。其实著名的Reflector.NET反编译工具,就是利用反射的原理。还有Microsoft Visual Studio 中的调试,背后也是利用反射技术..

    具体的使用代码如下(都有详细的使用说明,注释。读者可以一目了然):

    using System; 

    using System.Collections.Generic; 

    using System.Linq; 

    using System.Text; 

    using System.Reflection; 

    namespace Demo 

        class Program 

        { 

            static void Main(string[] args) 

            { 

               // reflectorInfo(); 

                reflectorDemo(); 

                Console.ReadKey(); 

            } 

            /// <summary> 

            /// 利用反射去调用程序集中(包含的类)所包含的方法,属性,成员... 

            /// </summary> 

            public static void reflectorDemo()  

            { 

                Assembly ass; 

                Type type; 

                MethodInfo method; 

                try 

                { 

                    ass = Assembly.LoadFile(@"F:ProjectsReflectorTestReflectorTestinDebug ReflectorTest.DLL");//根据物理DLL路径尝试加载 

                    type = ass.GetType("ReflectorTest.Test");//根据类型名称,反射出该类型(注意格式是:“命名空间.类名”) 

                    object o =Activator.CreateInstance(type);//创建该类型的对象实例 

                    method=type.GetMethod("sayHello");//反射获取方法(实例方法) 

                   string s = (string)method.Invoke(o,new string[] {"dinglang"});//调用实例方法 

                   Console.WriteLine("调用实例方法返回:"+s); 

                    method=type.GetMethod("noParm");//无参方法 

                    s= (string) method.Invoke(o,null);//调用无参函数 

                    Console.WriteLine("调用无参方法返回:"+s); 

                    //type.GetProperties()//获取该类型下面的所有公共属性 

                     

                    method=type.GetMethod("staticMethod");//静态函数 

                    s=(string)method.Invoke(null,new string[]{"dinglang"});//调用静态方法 

                    Console.WriteLine("调用静态方法返回:"+s); 

                    //根据指定的属性名称,获得属性值 

                    type.GetProperty("Name").GetValue(o,null); 

                    //给属性设值 

                    type.GetProperty("Name").SetValue(o, "dinglang", null); 

                } 

                catch (Exception) 

                { 

                    throw; 

                } 

                finally 

                { 

                      ass=null; 

                    type=null; 

                    method=null; 

                    

                } 

                

            } 

            /// <summary> 

            /// 利用反射获取程序集中类,类的成员(方法,属性等) 

            /// </summary> 

            public static void reflectorInfo()  

            { 

                Assembly ass = Assembly.LoadFrom(@"F:ProjectsReflectorTestReflectorTestinDebugReflectorTest.DLL");//加载程序集 

                Module[] modules = ass.GetModules();//模块信息   

                Type[] types = ass.GetTypes();//获取该程序集所包含的所有类型 

                foreach (var item in types) 

                { 

                    Console.WriteLine("所包含的类型类型名称:" + item.Name); 

                    MethodInfo[] methods = item.GetMethods();//获取该类型下所包含的方法信息 

                    foreach (var method in methods)  

                    { 

                        Console.WriteLine("该类下所包含的方法名称:"+method.Name); 

                    } 

                    PropertyInfo[] PropertyInfo = item.GetProperties(); 

                    foreach (var pro in PropertyInfo) 

                    { 

                        Console.WriteLine("该类下所包含的属性名称:" + pro.Name); 

                    } 

                } 

            } 

        } 

    读者可以参照以上代码,自己实际动手敲代码试试。还不夸张的说,当你真正学会了“反射”后,你会爱上“反射”。但是值得提醒的是:反射可能会很耗性能哦。希望大家在适当的场合下合理使用。

    反射文章介绍

    一、  反射就是动态发现类型信息的能力。它帮助程序设计人员在程序运行时利用一些信息去动态地使用类型,这些信息在设计时是未知的,这种能力类型于后期绑定。反射还支持的更高级的行为,能在运行时动态创建新类型,并且对这些新类型的操作进行调用。

    二、一些在反射中经常使用的类

    Assembly类

          Assembly类是可重用、无版本冲突并且可自我描述的公共语言运行库应用程序构造块。可以使用Assembly.Load和Assembly.LoadFrom方法动态地加载程序集。

    Type类

          反射的中心是System.Type类。System.Type类是一个抽象类,代表公用类型系统中的一种类型。这个类使您能够查询类型名、类型中包含的模块和名称空间、以及该类型是一个数值类型还是一个引用类型。
    System.Type类使您能够查询几乎所有与类型相关的属性,包括类型访问限定符、类型是否、类型的COM属性等等。

    Activator类

          Activator类支持动态创建.NET程序集和COM对象。可以通过CreateComInstanceFrom、CreateInstance、 CreateInstanceFrom、GetObject四个静态方法加载COM对象或者程序集,并能创建指定类型的实例。

    Binder类

          Binder类是一个用于执行类型转换的绑定器,Type对象的InvokeMember方法接受Binder对象,这个对象描述了如何将传递给InvokeMember的参数转换成方法实际需要的类型。
          Binder类是一个抽象类,要创建绑定器,需要重写方法BindToMethod、BindToField、SelectMehtod、SelectProperty和ChangeType。

    DefaultMemberAttribute类

        DefaultMemberAttribute类用于类型并带有一个指明默认成员名称的字符串参数。能够通过InvokeMember调用默认成员,而不需要传递调用成员的名称。当需要绑定器但不需要特别的绑定行为时就可以使用它。

    三、还有一些对元素类型信息描述的类,ConstrutorInfo(构造函数)、MethodInfo(方法)、FieldInfo(字段)、 PropertyInfo(属性)、EventInfo(事件)、MemberInfo(成员)、ParameterInfo(参数)。如果查询得到了具 有任何类型信息的实例,就可以获得该类型中任意元素的类型信息,当然出于安全原因,不保证会得到程序集中的任何信息。

    四、示例

    类定义

    复制代码
    using System;
    using System.Collections.Generic;
    using System.Text;

    namespace ReflectionSample
    {
    /**//**//**////
    /// 说明:一个简单的类
    /// 作者:文野
    /// 联系:stwyhm.cnblog.com
    ///
    public class ClassSample
    {
    // 默认构造
    public ClassSample()
    {
    this.name = "您调用了默认构造创建了一个类实例。";
    }

    // 带参构造
    public ClassSample(string name)
    {
    this.name = name;
    }

    // 字段
    public string name;

    public string Field;

    // 属性
    private string property;
    public string Property
    {
    set { this.property = value; }
    get { return property; }
    }

    // public方法
    public string PublicClassMethod()
    {
    return string.Format("您反射了一个Public方法");
    }

    // private方法
    private string PrivateClassMethod()
    {
    return string.Format("您反射了一个Private方法");
    }

    // static方法
    public static string StaticMethod()
    {
    return "您反射了一个Static方法";
    }

    // 帶參方法
    public string ParameterMethod(string para)
    {
    return para;
    }

    public event EventHandler eventHandler;

    public void DoEvent()
    {
    eventHandler(null,EventArgs.Empty);
    }
    }
    }

    复制代码

    反射示例

    复制代码
    using System;
    using System.Data;
    using System.Configuration;
    using System.Web;
    using System.Web.Security;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Web.UI.WebControls.WebParts;
    using System.Web.UI.HtmlControls;

    using System.Reflection;
    using ReflectionSample;

    /**//**//**////
    /// 说明:一个简单的使用反射示例
    /// 作者:文野
    /// 联系:stwyhm.cnblog.com
    ///
    public partial class _Default : System.Web.UI.Page
    {
    protected void Page_Load(object sender, EventArgs e)
    {
    string path = Server.MapPath(Request.Path);
    string filePath = path.Substring(0, path.LastIndexOf(''\'')) + @"inReflectionSample.dll";
    // 获取程序集
    Assembly classSampleAssembly = Assembly.LoadFrom(filePath);

    // 从程序集中获取指定对象类型
    Type classSampleType = classSampleAssembly.GetType("ReflectionSample.ClassSample");

    使用Activator创建一个实例使用Activator创建一个实例#region 使用Activator创建一个实例

    // 通过对象类型创建对象实例
    ClassSample s1 = Activator.CreateInstance(classSampleType) as ClassSample;

    Response.Write(s1.name + "(使用Activator创建一个实例)");

    #endregion

    动态调用构造函数动态调用构造函数#region 动态调用构造函数

    // 调用无参构造
    ConstructorInfo studentConstructor1 = classSampleType.GetConstructor(new Type[] { });
    ClassSample s2 = studentConstructor1.Invoke(new object[] { }) as ClassSample;
    Response.Write(s2.name + "");

    // 调用有参构造
    ConstructorInfo studentConstructor2 = classSampleType.GetConstructor(new Type[] { typeof(string) });
    ClassSample s3 = studentConstructor2.Invoke(new object[] { "您调用了有参构造创建了一个类实例。" }) as ClassSample;
    Response.Write(s3.name + "");

    #endregion

    反射方法反射方法#region 反射方法

    // 调用非静态方法
    string returnValue1 = classSampleType.InvokeMember("PublicClassMethod", BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Instance, null, s1, new object[] { }) as string;
    Response.Write(returnValue1 + "");

    // 调用静态方法
    string returnValue2 = classSampleType.InvokeMember("StaticMethod", BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static, null, s1, new object[] { }) as string; Response.Write(returnValue2 + ""); // 调用私有方法 string returnValue3 = classSampleType.InvokeMember("PrivateClassMethod", BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Instance, null, s1, new object[] { }) as string; Response.Write(returnValue3 + ""); #endregion //反射参数反射参数#region 反射参数 MethodInfo parameterMethod = classSampleType.GetMethod("ParameterMethod"); ParameterInfo[] paras = parameterMethod.GetParameters(); for (int i = 0; i ", new object[] { paras[i].Name, paras[i].ParameterType.ToString(), paras[i].IsOptional.ToString(), paras[i].Position.ToString(), paras[i].DefaultValue.ToString() })); #endregion //反射属性反射属性#region 反射属性 classSampleType.InvokeMember("Property", BindingFlags.SetProperty | BindingFlags.Public | BindingFlags.Instance, null, s1, new object[] { "您反射了一个属性" }); string returnValue4 = classSampleType.InvokeMember("Property", BindingFlags.GetProperty | BindingFlags.Public | BindingFlags.Instance, null, s1, new object[] { }) as string; Response.Write(returnValue4 + ""); #endregion //反射字段反射字段#region 反射字段 classSampleType.InvokeMember("Field", BindingFlags.SetField | BindingFlags.Public | BindingFlags.Instance, null, s1, new object[] { "您反射了一个字段" }); string returnValue5 = classSampleType.InvokeMember("Field", BindingFlags.GetField | BindingFlags.Public | BindingFlags.Instance, null, s1, new object[] { }) as string; Response.Write(returnValue5 + ""); #endregion }}
    复制代码

    五、.net反射机制

    .net反射机制为创建对象和调用其他方法提供了替代方案。比如为了提高代码的灵活性。但是问题确是我们要编写更多的代码来实现。
    使用反射机制是有一些缺点的。其最大的缺点就是编译器无法对对象进行类型检查,此时IDE的智能感知将无能为力。但是他的真正优势又在什么地方呢?它提供了一种手段,将指定具体类推迟到了运行时刻。
    使用反射机制调用方法的四步曲:
    1 加载程序集
    2 获取类的类型
    3 创建该类的实例
    4 调用该实例的方法
    System.Reflection.Assembly类中有两个静态方法Assembly.Load(string assemblyName)和Assembly.LoadFrom(string fileName)来把程序集加载到应用程序序域中。
    PS:在。NET中当一个对象被创建时,幕后到底发生了什么?当我们运行某一个应用程序时,.NET CLR会首先创建一个应用程序域来容纳这个应用程序,接着将应该引用的程序集加载到应用程序域中。其中MSCorLib.dll是一个程序集,它包含了很多系统命名空间及其子命名空间中的类:System;System.Text,System.IO等。该程序集合中。然后CLR加载正在运行的应用程序所属的程序集。
    DEMO:

    (1)namespace ClassLibrarySport

    {

        public abstract class Sport

        {

            protected string name;

            public abstract string GetName();

            public abstract string GetDuration();

        }

    }

    = = = = = == = == = == = == = == = == = == = == = == = == = == = == = == = == = == = =

    (2)namespace ClassLibrarySomeSports//该项目添加了对(1)的引用

    {

        public class Football : ClassLibrarySport.Sport

        {

            public Football()

            {

                name = "Football";

            }

            public override string GetName()

            {

                return name;

            }

            public override string GetDuration()

            {

                return "four 15 minute quarters";

            }

        }

    }

    = = = = = == = == = == = == = == = == = == = == = == = == = == = == = == = == = == = =

    (3)namespace ConsoleAssemblyTest//该项目添加了对(1)的引用

    {

        class Program

        {

            static void Main(string[] args)

            {

                Assembly assembly = Assembly.LoadFrom(@"E:ClassLibrarySomeSports

    binDebugClassLibrarySomeSports.dll");

                Type[] types = assembly.GetTypes();

     

                Console.WriteLine("Get Type From ClassLibrarySomeSports.dll:");

                for (int i = 0; i < types.Length; i++)

                {

                    Console.WriteLine(types[i].Name);

                }

     

                //使用GetConstructor()方法获取对应类型的构造器,从而构造出该类型的对象

                Console.WriteLine("Use Method GetConstructor():");

                ConstructorInfo ci = types[0].GetConstructor(new Type[0]);

                ClassLibrarySport.Sport sport = (ClassLibrarySport.Sport)ci.Invoke(new object[0]);

                Console.WriteLine(sport.GetName() + " has " + sport.GetDuration());

     

                //使用Activator.CreateInstance()方法构造出该类型的对象

    //使用assembly.CreateInstance()返回为null,??

                Console.WriteLine("Use Method CreateInstance():");

                ClassLibrarySport.Sport sport1 = (ClassLibrarySport.Sport)

    Activator.CreateInstance(types[0]);

                Console.WriteLine(sport1.GetName() + " has " + sport1.GetDuration());

     

                //反射指定类型中的名称为“GetDuration”的方法,通过Invoke()方法执行该方法

                object objSport = Activator.CreateInstance(types[0]);

                MethodInfo method = types[0].GetMethod("GetDuration");

                object o = method.Invoke(objSport, new object[0]);

                Console.WriteLine(o as string);

     

                Console.Read();

            }

        }

    }

    = = = = = == = == = == = == = == = == = == = == = == = == = == = == = == = == = == = =

    Output:

    Get Type From ClassLibrarySomeSports.dll:

    Football

    Use Method GetConstructor():

    Football has four 15 minute quarters

    Use Method CreateInstance():

    Football has four 15 minute quarters

    four 15 minute quarters

  • 相关阅读:
    递推&&矩阵加速
    洛谷 P1217 [USACO1.5]回文质数 Prime Palindromes
    总结一下当前阶段我认为比较常用的字符串操作
    关于递归与递推
    P1553 数字反转(升级版)
    关于C++读入数字按位取出与进制转换问题
    一本通题库 1058:求一元二次方程
    弄懂goroutine调度原理
    线程实现模型
    gin-jwt对API进行权限控制
  • 原文地址:https://www.cnblogs.com/sdya/p/4572058.html
Copyright © 2020-2023  润新知