wsky's blog,Record my technical life

just coding

导航

反射技术和设计模式

 

    反射(Reflection.NET中的重要机制,通过放射,可以在运行时获得.NET中每一个类型(包括类、结构、委托、接口和枚举等)的成员,包括方法、属性、事件,以及构造函数等。还可以获得每个成员的名称、限定符和参数等。有了反射,即可对每一个类型了如指掌。如果获得了构造函数的信息,即可直接创建对象,即使这个对象的类型在编译时还不知道。(:加载程序集,进行后期绑定…load())

 

1.1 .NET可执行应用程序结构

 

  程序代码在编译后生成可执行的应用,我们首先要了解这种可执行应用程序的结构。应用程序结构分为应用程序域程序集模块类型成员几个层次,公共语言运行库加载器管理应用程序域,这种管理包括将每个程序集加载到相应的应用程序域以及控制每个程序集中类型层次结构的内存布局。

 

  程序集包含模块,而模块包含类型,类型又包含成员,反射则提供了封装程序集、模块和类型的对象。我们可以使用反射动态地创建类型的实例,将类型绑定到现有对象或从现有对象中获取类型,然后调用类型的方法或访问其字段和属性。反射通常具有以下用途。

1)使用Assembly定义和加载程序集,加载在程序集清单中列出模块,以及从此程序集中查找类型并创建该类型的实例

  (2)使用Module了解包含模块的程序集以及模块中的类等,还可以获取在模块上定义的所有全局方法或其他特定的非全局方法。

  (3)使用ConstructorInfo了解构造函数的名称、参数、访问修饰符(如pulic private)和实现详细信息(如abstractvirtual)等。使用TypeGetConstructorsGetConstructor方法来调用特定的构造函数。

  (4)使用MethodInfo了解方法的名称、返回类型、参数、访问修饰符(如pulic private)和实现详细信息(如abstractvirtual)等。使用TypeGetMethodsGetMethod方法来调用特定的方法。

  (5)使用FiedInfo了解字段的名称、访问修饰符(如publicprivate)和实现详细信息(如static)等,并获取或设置字段值。

  (6)使用EventInfo了解事件的名称、事件处理程序数据类型、自定义属性、声明类型和反射类型等,添加或移除事件处理程序。

  (7)使用PropertyInfo了解属性的名称、数据类型、声明类型、反射类型和只读或可写状态等,获取或设置属性值。

  (8)使用ParameterInfo了解参数的名称、数据类型、是输入参数还是输出参数,以及参数在方法签名中的位置等

 

Ps : 以上都是后期绑定所用到的对应的调用

System.Reflection.Emit命名空间的类提供了一种特殊形式的反射,可以在运行时构造类型。反射也可用于创建称为类型浏览器的应用程序,使用户能够选择类型,然后查看有关选定类型的信息。

 

 

1.3 在设计模式实现中使用反射技术

  采用反射技术可以简化工厂的实现。

 在以下情况下,适用于工厂方法模式: tech.it168.com/n/2007-05-09/200705091437406.shtml

1.
当一个类不知道它所必须创建的对象的类的时候。

2.
当一个类希望由它的子类来指定它所创建的对象的时候。

3.
当类将创建对象的职责委托给多个帮助子类中的某一个,并且你希望将哪一个帮助子类是代理者这一信息局部化的时候

  (1)工厂方法:通过反射可以将需要实现的子类名称传递给工厂方法,这样无须在子类中实现类的实例化。

  (2)抽象工厂:使用反射可以减少抽象工厂的子类。

 

  采用反射技术可以简化工厂代码的复杂程度,在.NET项目中,采用反射技术的工厂已经基本代替了工厂方法。采用反射技术可以极大地简化对象的生成,对以下设计模式的实现也有很大影响。

 

  (1)命令模式:可以采用命令的类型名称作为参数直接获得命令的实例,并且可以动态执行命令。

  (2)享元模式:采用反射技术实例化享元可以简化享元工厂。

 

 

 

 

 

 

一个简单例子:

 
Namespace ReflectionExample
{
 
class Class1
{
[STAThread]
 
static void Main (string [ ] args)
{
System.Console.WriteLine(“列出程序集中的所有类型”);
   Assembly a = Assembly.LoadFrom (“ReflectionExample.exe”);
   Type[ ] mytypes = a.GetTypes( );
   Foreach (Type t in mytypes)
   {
     System.Console.WriteLine ( t.Name );
   }
    System.Console.ReadLine ( );
System.Console.WriteLine (“列出HellWord中的所有方法” );
Type ht = typeof(HelloWorld);
MethodInfo[] mif = ht.GetMethods();
 
foreach(MethodInfo mf in mif)
{
    System.Console.WriteLine(mf.Name);
}
System.Console.ReadLine();
System.Console.WriteLine("实例化HelloWorld,并调用SayHello方法");
Object obj = Activator.CreateInstance(ht);
 
string[] s = {"zhenlei"};
Object bojName = Activator.CreateInstance(ht,s);
BindingFlags flags = (BindingFlags.NonPublic|BindingFlags.
Public|BindingFlags.Static|BindingFlags.
Instance|BindingFlags.DeclaredOnly);
MethodInfo msayhello = ht.GetMethod("SayHello");
msayhello.Invoke(obj,null);
msayhello.Invoke(objName,null);
System.Console.ReadLine();
}
}
}
 
using System;
 
namespace ReflectionExample
{
 
public class HelloWorld
{
  string myName = null;
  public HelloWorld(string name)
  {
      myName = name;
  }
  public HelloWorld() : this(null)
  {}
  public string Name
  {
      get
      {
    return myName;
      }
  }
  public void SayHello()
  {
      if(myName == null)
      {
    System.Console.WriteLine("Hello World");
      }
      else
      {
    System.Console.WriteLine("Hello," + myName);
      }
  }
}
}

 

posted on 2007-08-21 11:05  wsky  阅读(354)  评论(2编辑  收藏  举报