一直在用反射,可是却没有系统了解。这几天好好看了下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.源码