且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

.net反射

更新时间:2022-10-02 22:57:15

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

 

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

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(参数)。如果查询得到了具有任何类型信息的实例,就可以获得该类型中任意元素的类型信息,当然出于安全原因,不保证会得到程序集中的任何信息。

 

四、示例

类定义

 


  1. 代码  
  2.  
  3. using System;  
  4. using System.Collections.Generic;  
  5. using System.Text;  
  6.  
  7. namespace ReflectionSample  
  8. {  
  9.     /**//**//**////   
  10.     /// 说明:一个简单的类  
  11.     /// 作者:文野  
  12.     /// 联系:stwyhm.cnblog.com  
  13.     ///   
  14.     public class ClassSample  
  15.     {  
  16.         // 默认构造  
  17.         public ClassSample()  
  18.         {  
  19.             this.name = "您调用了默认构造创建了一个类实例。";  
  20.         }  
  21.  
  22.         // 带参构造  
  23.         public ClassSample(string name)  
  24.         {  
  25.             this.name = name;  
  26.         }  
  27.  
  28.         // 字段   
  29.         public string name;  
  30.  
  31.         public string Field;  
  32.  
  33.         // 属性  
  34.         private string property;  
  35.         public string Property  
  36.         {  
  37.             set { this.property = value; }  
  38.             get { return property; }  
  39.         }  
  40.  
  41.         // public方法   
  42.         public string PublicClassMethod()  
  43.         {  
  44.             return string.Format("您反射了一个Public方法");  
  45.         }  
  46.  
  47.         // private方法  
  48.         private string PrivateClassMethod()  
  49.         {  
  50.             return string.Format("您反射了一个Private方法");  
  51.         }  
  52.  
  53.         // static方法  
  54.         public static string StaticMethod()  
  55.         {  
  56.             return "您反射了一个Static方法";  
  57.         }  
  58.  
  59.         // 帶參方法  
  60.         public string ParameterMethod(string para)  
  61.         {  
  62.             return para;  
  63.         }  
  64.  
  65.         public event EventHandler eventHandler;  
  66.  
  67.         public void DoEvent()  
  68.         {  
  69.             eventHandler(null,EventArgs.Empty);  
  70.         }  
  71.     }  

反射示例

 


  1. 代码  
  2.  
  3. using System;  
  4. using System.Data;  
  5. using System.Configuration;  
  6. using System.Web;  
  7. using System.Web.Security;  
  8. using System.Web.UI;  
  9. using System.Web.UI.WebControls;  
  10. using System.Web.UI.WebControls.WebParts;  
  11. using System.Web.UI.HtmlControls;  
  12.  
  13. using System.Reflection;  
  14. using ReflectionSample;  
  15.  
  16. /**//**//**////   
  17. /// 说明:一个简单的使用反射示例  
  18. /// 作者:文野  
  19. /// 联系:stwyhm.cnblog.com  
  20. ///   
  21. public partial class _Default : System.Web.UI.Page  
  22. {  
  23.     protected void Page_Load(object sender, EventArgs e)  
  24.     {  
  25.         string path = Server.MapPath(Request.Path);  
  26.         string filePath = path.Substring(0, path.LastIndexOf(''\\'')) + @"\bin\ReflectionSample.dll";  
  27.         // 获取程序集  
  28.         Assembly classSampleAssembly = Assembly.LoadFrom(filePath);  
  29.  
  30.         // 从程序集中获取指定对象类型  
  31.         Type classSampleType = classSampleAssembly.GetType("ReflectionSample.ClassSample");  
  32.  
  33.         使用Activator创建一个实例使用Activator创建一个实例#region 使用Activator创建一个实例  
  34.  
  35.         // 通过对象类型创建对象实例  
  36.         ClassSample s1 = Activator.CreateInstance(classSampleType) as ClassSample;  
  37.  
  38.         Response.Write(s1.name + "(使用Activator创建一个实例)");  
  39.  
  40.         #endregion  
  41.  
  42.         动态调用构造函数动态调用构造函数#region 动态调用构造函数  
  43.  
  44.         // 调用无参构造  
  45.         ConstructorInfo studentConstructor1 = classSampleType.GetConstructor(new Type[] { });  
  46.         ClassSample s2 = studentConstructor1.Invoke(new object[] { }) as ClassSample;  
  47.         Response.Write(s2.name + "");  
  48.  
  49.         // 调用有参构造  
  50.         ConstructorInfo studentConstructor2 = classSampleType.GetConstructor(new Type[] { typeof(string) });  
  51.         ClassSample s3 = studentConstructor2.Invoke(new object[] { "您调用了有参构造创建了一个类实例。" }) as ClassSample;  
  52.         Response.Write(s3.name + "");  
  53.  
  54.         #endregion  
  55.  
  56.         反射方法反射方法#region 反射方法  
  57.  
  58.         // 调用非静态方法  
  59.         string returnValue1 = classSampleType.InvokeMember("PublicClassMethod", BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Instance, null, s1, new object[] { }) as string;  
  60.         Response.Write(returnValue1 + "");  
  61.  
  62.         // 调用静态方法  
  63.         string returnValue2 = classSampleType.InvokeMember("StaticMethod", BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static, null, s1, new object[] { }) as string;  
  64.         Response.Write(returnValue2 + "");  
  65.  
  66.         // 调用私有方法  
  67.         string returnValue3 = classSampleType.InvokeMember("PrivateClassMethod", BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Instance, null, s1, new object[] { }) as string;  
  68.         Response.Write(returnValue3 + "");  
  69.  
  70.         #endregion  
  71.  
  72.         //反射参数反射参数#region 反射参数  
  73.  
  74.         MethodInfo parameterMethod = classSampleType.GetMethod("ParameterMethod");  
  75.         ParameterInfo[] paras = parameterMethod.GetParameters();  
  76.         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() }));  
  77.  
  78.         #endregion  
  79.  
  80.         //反射属性反射属性#region 反射属性  
  81.  
  82.         classSampleType.InvokeMember("Property", BindingFlags.SetProperty | BindingFlags.Public | BindingFlags.Instance, null, s1, new object[] { "您反射了一个属性" });  
  83.         string returnValue4 = classSampleType.InvokeMember("Property", BindingFlags.GetProperty | BindingFlags.Public | BindingFlags.Instance, null, s1, new object[] { }) as string;  
  84.         Response.Write(returnValue4 + "");  
  85.  
  86.         #endregion  
  87.  
  88.         //反射字段反射字段#region 反射字段  
  89.  
  90.         classSampleType.InvokeMember("Field", BindingFlags.SetField | BindingFlags.Public | BindingFlags.Instance, null, s1, new object[] { "您反射了一个字段" });  
  91.         string returnValue5 = classSampleType.InvokeMember("Field", BindingFlags.GetField | BindingFlags.Public | BindingFlags.Instance, null, s1, new object[] { }) as string;  
  92.         Response.Write(returnValue5 + "");  
  93.  
  94.         #endregion  
  95.     }  

五、.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\

bin\Debug\ClassLibrarySomeSports.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


本文转自linzheng 51CTO博客,原文链接:http://blog.51cto.com/linzheng/1081717