首页 > 其他分享 >.net的反射机制

.net的反射机制

时间:2023-08-08 22:38:12浏览次数:36  
标签:反射 string System BindingFlags using net type 机制


学习4点:

1.反射有什么用,什么情况下用反射。                  (参考资料http://dotnet.9sssd.com/csbase/art/733)

2.通过简单的例子理解反射的运用。                     (参考资料http://www.2cto.com/kf/201110/109636.html)

3.通过复杂的例子理解更多反射的用法,语法。(参考资料ttp://blog.163.com/shensc@126/blog/static/13128965220106183155664/)

4.反射的性能优化。                                                 (参考资料http://www.soaspx.com/dotnet/asp.net/tech/tech_20120407_8898.html)


1.反射有什么用,什么情况下用反射。


反射机制就是你给它一个类或者程序集,它就能知道这个类或者程序集中有什么方法和类型属性,然后模拟出这个类中的方法和类型属性。


这样我们就可以很灵活动态的创建需要的类,调用相应的方法。


一般我们遇到多个类似的功能实现用同一个接口时但还不能确定是用哪一个实现时就可以用反射作出相应的判断。


在抽象工厂模式中经常用反射,典型的例子是数据读取层。

一个项目可能用到SqlSever,Access,Orace或者Txt,XML来当存取数据,他们的方法都是统一,比如增,删,修,读等。

这个时候就是定义一个IDataAccess接口,这个接口定义了统一的方法,增,删,修,读等,然后分别用不同的实现类来继承这个接口,比如SqlServer类,XmL类,定义为SqlServerDataAccess,XMLDataAccess,他们都继承IDataAccess。

在应用的时候项目可以通过简单的修改或者配置来使用Sqlserver或者XML数据库,这个时候就可以使用反射来决定接口IDataAccess到底使用哪个实现类。

抽象工厂模式中使用配置文件来设置使用Sqlserver还是XML数据实现类。在配置文件中定义“程序集和命名空间类名”的信息,这样通过修改配置文件就可以决定使用Sqlserver还是XML数据实现类。


2.通过简单的例子理解反射的运用。

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


.net的反射机制_System

代码如下:

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 "你好:" + name+"我是一个有参的方法"; 

        } 

        /// <summary> 

        /// 无参的方法 

        /// </summary> 

        /// <returns></returns> 

        public string noParm()  

        { 

            return "我是一个无参方法"; 

        } 

    } 

}




然后在解决方案里添加一个窗口


.net的反射机制_System_02


.net的反射机制_程序集_03

拉入两个按钮 每个按钮执行一个反射函数:reflectorDemo()执行类库中的函数, reflectorInfo()遍历出类库中所有的方法,属性,类型。


.net的反射机制_System_04



代码如下:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Reflection;
using ReflectorTest;


namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }


        private void button1_Click(object sender, EventArgs e)
        {
            reflectorDemo(); 
        }


        private void button2_Click(object sender, EventArgs e)
        {
            reflectorInfo(); 
        }




         public static void reflectorDemo()  
        { 


            Assembly ass; 
            Type type; 
            MethodInfo method; 
           try 
            {
                ass = Assembly.Load("ReflectorTest"); //根据命名空间加载
                //ass = Assembly.LoadFile("ReflectorTest.DLL");根据文件名称尝试加载 
                type = ass.GetType("ReflectorTest.Test");//根据类型名称,反射出该类型(注意格式是:“命名空间.类名”) 
                object o =Activator.CreateInstance(type);//创建该类型的对象实例 
               
               method=type.GetMethod("sayHello");//反射获取方法(实例方法) 
               string s = (string)method.Invoke(o,new string[] {"张三"});//调用实例方法 
               MessageBox.Show("调用实例方法返回:" + s); 

                method=type.GetMethod("noParm");//无参方法 
                s= (string) method.Invoke(o,null);//调用无参函数 
                MessageBox.Show("调用无参方法返回:" + s);  


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

               method=type.GetMethod("staticMethod");//静态函数 
                s = (string)method.Invoke(null, new string[] { "张三" });//调用静态方法 
               MessageBox.Show("调用静态方法返回:"+s); 

               //根据指定的属性名称,获得属性值 
               type.GetProperty("Name").GetValue(o,null); 
                //给属性设值 
                type.GetProperty("Name").SetValue(o, "张三", null); 


            } 
            catch (Exception) 
            { 
                throw; 
            } 
            finally 
            { 
                  ass=null; 
                type=null; 
                method=null;            
            }         
        } 
        /// <summary> 
        /// 利用反射获取程序集中类,类的成员(方法,属性等) 
        /// </summary> 
        public static void reflectorInfo()  
        {
            Assembly ass = Assembly.Load("ReflectorTest");
          //  Assembly ass = Assembly.LoadFrom("ReflectorTest.DLL");加载程序集 

            Module[] modules = ass.GetModules();//模块信息   
            Type[] types = ass.GetTypes();//获取该程序集所包含的所有类型 
            foreach (var item in types) 
            { 
                MessageBox.Show("所包含的类型类型名称:" + item.Name); 
                MethodInfo[] methods = item.GetMethods();//获取该类型下所包含的方法信息 
                foreach (var method in methods)  
                {
                    MessageBox.Show("该类下所包含的方法名称:" + method.Name); 
          } 
                PropertyInfo[] PropertyInfo = item.GetProperties(); 
                foreach (var pro in PropertyInfo) 
                {
                    MessageBox.Show("该类下所包含的属性名称:" + pro.Name); 
                } 
            } 
        } 
    } 
}




把窗口设置为启动项


.net的反射机制_System_05


并对窗体添加 ReflectorTest类库的关联


.net的反射机制_User_06

.net的反射机制_程序集_07




否则useing  ReflectorTest  会报找不到。

.net的反射机制_User_08



 F5热键 测试结果:

点击

.net的反射机制_System_09

结果:

.net的反射机制_User_10

.net的反射机制_程序集_11

.net的反射机制_程序集_12


发现实现了程序集中的方法。

但我们并没有(直接)调用程序集中的函数,这就是反射的作用。模拟出程序集中的函数实现。


点击

.net的反射机制_User_13


结果:

.net的反射机制_程序集_14

.net的反射机制_System_15

。。。。等等 

遍历了程序集中的所有方法和属性。也就是说通过反射我们能知道程序集里有什么方法函数和属性。



3.通过复杂的例子理解更多反射的用法,语法


解决方案构造方法与简单例子类似。

直接上代码,以后用到相关语法的时候可以学习着写:


类库中的代码:


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

namespace Models
{
    public class User
    {
        /// <summary>
        /// 字段
        /// </summary>
        public string Field;

        private int age;
        /// <summary>
        /// 属性:年龄
        /// </summary>
        public int Age
        {
            get { return age; }
            set { age = value; }
        }

        private string name;
        /// <summary>
        /// 属性:名称
        /// </summary>
        public string Name
        {
            get { return name; }
            set { name = value; }
        }

        /// <summary>
        /// 无参数构造函数
        /// </summary>
        public User()
        {
            this.name = "调用了无参数的构造函数";
        }

        /// <summary>
        /// 带参构造函数
        /// </summary>
        public User(string name)
        {
            this.Name = name;
           // this.Age = age;
        }

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

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

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

        /// <summary>
        /// 无带参方法
        /// </summary>
        public string Show1()
        {
            return string.Format("我的名字叫:{0},今年{1}岁了!", this.Name, this.Age);
        }

        /// <summary>
        /// 带参方法
        /// </summary>
        public string Show(string aihao)
        {
            return string.Format("大家好,我的爱好是:{0}!", aihao);
        }

        /// <summary>
        /// 自定义事件类型
        /// </summary>
        public event EventHandler eventHandler;

        /// <summary>
        /// 处理事件
        /// </summary>
        public void DoEvent()
        {
            eventHandler(null, EventArgs.Empty);
        }
    }
}





窗体的代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Reflection;
using Models;

namespace test
{
    public partial class Form3 : Form
    {
        public Form3()
        {
            InitializeComponent();
        }

        private void Form3_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (DialogResult.OK != MessageBox.Show("你确定要退出系统", "提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Information))
            {
                e.Cancel = true;
                //  MessageBox.Show(e.CloseReason.ToString());
            }
            else
            {

            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void btnOk_Click(object sender, EventArgs e)
        {
            //获取程序集 
            Assembly assembly = Assembly.Load("Models");
            Assembly assembly2 = Assembly.LoadFrom("Models.dll");

            //从程序集中获取指定对象类型;
            Type type = assembly2.GetType("Models.User");

            //使用Activator创建一个实例使用Activator创建一个实例
            User user2 = Activator.CreateInstance(type) as User;
            //通过对象类型创建对象实例  
            User user = assembly.CreateInstance("Models.User") as User;

            // 调用无参构造
            ConstructorInfo studentConstructor = type.GetConstructor(new Type[] { });
            User user3 = studentConstructor.Invoke(new object[] { }) as User;

            //调用有参构造 
            ConstructorInfo studentConstructor2 = type.GetConstructor(new Type[] { typeof(string) });
            User user4 = studentConstructor.Invoke(new object[] { "您调用了有参构造创建了一个类实例。"}) as User;

            //调用非静态方法
            string returnValue = type.InvokeMember("PublicClassMethod", BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Instance, null, user, new object[] { }) as string;

            // 调用静态方法 .       
            string returnValue2 = type.InvokeMember("StaticMethod", BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static, null, user, new object[] { }) as string;

            // 调用私有方法 .       
            string returnValue3 = type.InvokeMember("PrivateClassMethod", BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Instance, null, user, new object[] { }) as string;


            //反射参数反射参数
            MethodInfo parameterMethod = type.GetMethod("Show");

            ParameterInfo[] paras = parameterMethod.GetParameters();
            for (int i = 0; i < paras.Length; i++)
            {
                MessageBox.Show(string.Format("参数名称:{0},参数类型:{1},是否可选:{2},位置:{3},默认值:{4}", paras[i].Name, paras[i].ParameterType.ToString(), paras[i].IsOptional.ToString(), paras[i].Position.ToString(), paras[i].DefaultValue.ToString()));

                //反射属性反射属性
                type.InvokeMember("Name", BindingFlags.SetProperty | BindingFlags.Public | BindingFlags.Instance, null, user, new object[] { "您反射了一个属性" });
                string returnValue4 = type.InvokeMember("Name", BindingFlags.GetProperty | BindingFlags.Public | BindingFlags.Instance, null, user, new object[] { }) as string;

                //反射字段反射字段
                type.InvokeMember("Field", BindingFlags.SetField | BindingFlags.Public | BindingFlags.Instance, null, user, new object[] { "您反射了一个字段" });
                string returnValue5 = type.InvokeMember("Field", BindingFlags.GetField | BindingFlags.Public | BindingFlags.Instance, null, user, new object[] { }) as string;
            }
        }
    }
}

BindingFlags用于指定你要得的的函数或者成员的类

BindingFlags.InvokeMethod指调用方法。

BindingFlags.SetProperty指设置属性

BindingFlags.GetProperty指得到属性

BindingFlags.SetField指设置字段

BindingFlags.GetField指得到字段


BindingFlags.Instance 或 BindingFlags.Static必须指定其一,以确定你要的是否是静态方法. 


BindingFlags.Instance ,反射的时候会去实例成员,也就是非静态的,你的方法是非静态的,就必须必须加上这个才行。


BindingFlags.Static ,要反射静态的方法就必须加上这个。



4.反射的性能优化。


我们用2.简单例子中的reflectorDemo()函数来学一下怎么优化。

public static void reflectorDemo()  
        { 


            Assembly ass; 
            Type type; 
            MethodInfo method; 
           try 
            {
                ass = Assembly.Load("ReflectorTest"); //根据命名空间加载
                //ass = Assembly.LoadFile("ReflectorTest.DLL");根据文件名称尝试加载 
                type = ass.GetType("ReflectorTest.Test");//根据类型名称,反射出该类型(注意格式是:“命名空间.类名”) 
                object o =Activator.CreateInstance(type);//创建该类型的对象实例 
               
               method=type.GetMethod("sayHello");//反射获取方法(实例方法) 
               string s = (string)method.Invoke(o,new string[] {"张三"});//调用实例方法 
               MessageBox.Show("调用实例方法返回:" + s); 

                method=type.GetMethod("noParm");//无参方法 
                s= (string) method.Invoke(o,null);//调用无参函数 
                MessageBox.Show("调用无参方法返回:" + s);  


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

               method=type.GetMethod("staticMethod");//静态函数 
                s = (string)method.Invoke(null, new string[] { "张三" });//调用静态方法 
               MessageBox.Show("调用静态方法返回:"+s); 

               //根据指定的属性名称,获得属性值 
               type.GetProperty("Name").GetValue(o,null); 
                //给属性设值 
                type.GetProperty("Name").SetValue(o, "张三", null); 


            } 
            catch (Exception) 
            { 
                throw; 
            } 
            finally 
            { 
                  ass=null; 
                type=null; 
                method=null;            
            }         
        }


比如:优化调用实例方法:

原反射:

type = ass.GetType("ReflectorTest.Test");//根据类型名称,反射出该类型(注意格式是:“命名空间.类名”) 
                object o =Activator.CreateInstance(type);//创建该类型的对象实例 
               
               method=type.GetMethod("sayHello");//反射获取方法(实例方法) 
               string s = (string)method.Invoke(o,new string[] {"张三"});//调用实例方法 
               MessageBox.Show("调用实例方法返回:" + s);



通过委托优化:


public delegate int AddMethod(string a); // 委托
type = ass.GetType("ReflectorTest.Test");//根据类型名称,反射出该类型(注意格式是:“命名空间.类名”)             
 object o =Activator.CreateInstance(type);//创建该类型的对象实例  
method=type.GetMethod("sayHello");//反射获取方法(实例方法) 

  var newMethod = (AddMethod)Delegate.CreateDelegate(typeof(AddMethod), obj, method);
  
string s = newMethod(new string[] {"张三"});//调用实例方法 
         MessageBox.Show("调用实例方法返回:" + s);
上面的代码看起来多了几行,而且还需要自定义一个委托,写起来挺麻烦的。因此我们的测试代码里面还实现了另外一种形式,其实它也是委托:


var newMethod = (Func<TestObject, string>)Delegate.CreateDelegate(typeof(Func<TestObject, string>), method);




通过.NET4动态编程的实现

dynamic obj = new Test();

 // 有木有发现这个代码超级简单? Test对应程序集中的类名。
      
string s =obj.sayHello(“张三”);

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

标签:反射,string,System,BindingFlags,using,net,type,机制
From: https://blog.51cto.com/u_16218512/7013063

相关文章

  • ASP.NET----jQuery插件flot绘画图表
    flot是一个基于jQuery的图表绘制插件效果挺好看的:参考资料:http://code.google.com/p/flot/ 谷歌官网http://www.flotcharts.org/flot/examples/categories/index.html 例子(可右键查看源文件看看代码)要用到的js文件以及中文api文档可以在这里下载(没分的M我,给你发)基本语......
  • Dubbo是干嘛的,Dubbo原理和机制,Dubbo的核心组件
    大家好,我是哪吒。Dubbo是一个高性能的JavaRPC框架。RPC是远程过程调用的缩写,其基本思想是:客户端像调用本地方法一样,通过网络请求调用远程服务器上的服务。Dubbo可以帮助我们更方便地构建分布式应用程序,它具有高效的远程调用、服务自动注册和发现、负载均衡、容错机制等众多特性,是......
  • .NET Core多线程 (2) 异步 - 上
    去年换工作时系统复习了一下.NETCore多线程相关专题,学习了一线码农老哥的《.NET5多线程编程实战》课程,我将复习的知识进行了总结形成本专题。本篇,我们来复习一下异步的相关知识点,预计阅读时间10分钟。理解异步的本质(1)异步是什么?举个例子,在高峰期去餐厅吃饭,会先排队拿个小票,......
  • .Net Core WebApi
    目录MiniMalAPiDemoProgram.csSwagger文档+信息Program.csAPI版本控制ApiVersion.csVersion1Controller.csProgram.cs生成注释解决跨域.Net后台请求封装返回数据压缩默认压缩Gzip压缩缓存接口缓存静态文件缓存MiniMalAPi最小的api,请求都写在Program.cs中,可以做微服务D......
  • Docker(.Net6) 环境下使用 Haukcode.WkHtmlToPdfDotNet
     背景: 项目使用的是.Net6+Docker,需要将数据生成PDF保存到第三方文件存储服务器上。引用NuGet:Haukcode.WkHtmlToPdfDotNet 这个插件还是满好用的,支持Windows、Docker.可以直接通过Url转PDF,也可以通过Html字符,生成PDF.官方地址:https://github.com/Hak......
  • 在windows上使用_netrc文件让Git记住用户名和密码(Linux文件名为.netrc)
    windowsnetrc文件是什么。根据我搜索到的结果,windowsnetrc文件是一种用于保存网络身份验证信息的文件,例如用户名和密码。它可以被一些命令行工具和应用程序使用,比如Git、curl、ftp等。windowsnetrc文件的格式如下:machine<hostname>login<username>password<password>......
  • Log4netHelper, 支持自定义日志文件生成间隔
    usinglog4net;usinglog4net.Appender;usinglog4net.Config;usinglog4net.Repository;usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;usingSystem.Threading.Tasks;usingstaticlog4net.Appender.FileAppender;namespa......
  • 记一次 .NET某报关系统 非托管泄露分析
    一:背景1.讲故事前段时间有位朋友找到我,说他的程序内存会出现暴涨,让我看下是怎么事情?而且还告诉我是在Linux环境下,说实话在Linux上分析.NET程序难度会很大,难度大的原因在于Linux上的各种开源工具主要是针对C/C++,和.NET一毛钱关系都没有,说到底微软在Linux上的调试领域支......
  • 掌握.NET多线程编程技术
    当涉及到处理并发任务、提高程序性能以及充分利用多核处理器时,.NET多线程编程技术就变得至关重要。在本篇博客中,我将为您介绍一些.NET多线程编程的基本概念和技术,并附上一些示例代码来帮助您更好地理解。为什么使用多线程编程?多线程编程允许在同一进程中同时执行多个线程,从而充分利......
  • ASP.NET Core 中的显示和编辑器模板
    显示模板和编辑器模板指定了自定义类型的用户界面布局。考虑下列 Address 模型:C#复制 publicclassAddress{publicintId{get;set;}publicstringFirstName{get;set;}=null!;publicstringMiddleName{get;set;}=null!;publicst......