反射学习笔记(1)
一直在用反射,可是却没有系统了解。这几天好好看了下Reflection命名空间,做个笔记。
1.什么叫反射。
我觉得.Net 中的反射 中的总结不错。
反射是一种宽泛的叫法,它通过 System.Reflection 命名空间 并 配合 System.Type 类,提供了在运行时(Runtime)对于 类型和对象(及其成员)的基本信息 以及 元数据(metadata)的访问能力。
你也可以这么理解,通过反射我们可以在运行时获得各种信息,如程序集、模块、类型、字段、属性、方法和事件,通过对类型动态实例化后,还可以对其执行操作。简单来说就是用string可以在runtime为所欲为的东西,实际上就是一个.net framework内建的万能工厂。一般用于插件式框架程序和设计模式的实现,当然反射是一种手段可以充分发挥其能量来完成你想做的任何事情(你可以通过反射调用程序集的private,internal等原本无法访问的类或者方法。)
2.如何使用反射
实例1: 三层项目中常用到, 工厂通过反射动态加载,实例化出数据层类实例,供业务层调用。
接口:IAnimal.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Reftext { public interface IAnimal { string Name(string aa); } } 实现类:Dog.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Reftext { public class Dog:IAnimal { public string Name(string aa) { return aa; } } }
业务层调用方法:
Reftext.IAnimal animal = (Reftext.IAnimal)Assembly.Load("Reftext").CreateInstance("Reftext.Dog"); string flag=animal.Name("dog");
实例2:如果类没有定义相关接口,如何访问public ,private,属性或方法等。
定义Userinfo类:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Reftext { internal class Userinfo { private string name; private int age; public Userinfo() { } private void ChangeName(string NewName) { name = NewName; } public void ChangeAge(int NewAge) { age = NewAge; } public string WriteInfo(string NewName, int NewAge) { return "您的信息:" +"姓名"+ NewName +" 年龄"+ NewAge.ToString(); } public void WriteNameOut(string NewName,out string OutName) { OutName = "Bill " + NewName; } private string GetString(string str) { return "一个参数"+str; } private string GetString(string str1, string str2) { return "两个参数"+str1 + str2; } public static string WriteName(string s) { return "名称为:" + s; } } }
使用方法:
Assembly ass = Assembly.Load("Reftext"); //public方法访问 object obj = ass.CreateInstance("Reftext.Userinfo"); var othermethod1 = obj.GetType().GetMethod("ChangeAge"); othermethod1.Invoke(obj, new object[] { 12 }); //private 方法访问 MethodInfo m0 = obj.GetType().GetMethod("ChangeName", BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[] { typeof(string) }, null); m0.Invoke(obj, new string[] { "111" }); //静态方法调用 var othermethodstatic = obj.GetType().GetMethod("WriteName"); othermethodstatic.Invoke(obj, new object[] { "static" }); //多个参数 var othermethod2 = obj.GetType().GetMethod("WriteInfo"); object flag2=othermethod2.Invoke(obj, new object[] {"夏明",12 }); //带out 参数 var othermethod3 = obj.GetType().GetMethod("WriteNameOut"); object[] invokeArgs3 = new object[] { "worton" ," husiton"}; othermethod3.Invoke(obj, invokeArgs3); object flag3 = invokeArgs3[1]; //方法重载的调用 MethodInfo m1 = obj.GetType().GetMethod("GetString", BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[] { typeof(string) }, null); MethodInfo m2 = obj.GetType().GetMethod("GetString", BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[] { typeof(string), typeof(string) }, null); m1.Invoke(obj, new string[] { "111" }); m2.Invoke(obj, new string[] { "111","222" });
注:Assembly加载程序集有多种方法:
Assembly.LoadFile
Assembly.Load 等 具体用法看看MSDN吧。
3.利用Type类获取程序集信息
Reftext.Dog dog= new Reftext.Dog(); Type type = dog.GetType(); Response.Write("类型名:" + type.Name+"</br>"); Response.Write("类全名:" + type.FullName + "</br>"); Response.Write("命名空间名:" + type.Namespace + "</br>"); Response.Write("程序集名:" + type.Assembly + "</br>"); Response.Write("模块名:" + type.Module + "</br>"); Response.Write("基类名:" + type.BaseType + "</br>"); Response.Write("是否类:" + type.IsClass + "</br>"); Response.Write("类的公共成员:"); MemberInfo[] memberInfos = type.GetMembers();//得到所有公共成员 foreach (var item in memberInfos) { // Console.WriteLine("{0}:{1}", item.MemberType, item); Response.Write(item.MemberType.ToString() +" "+ item.ToString() +"</br>"); }
参考:1.反射----重载的方法
2..Net 中的反射3.实例总结C#反射基础知识[原创]
4.源码