.NET反射、委托技术与设计模式

转载 2006年06月22日 18:13:00
1 反射技术与设计模式  
        反射(Reflection)是.NET中的重要机制,通过放射,可以在运 行时获得.NET中每一个类型(包括类、结构、委托、接口和枚举等)的成员,包括方法、属性、事件,以及构造函数等。还可以获得每个成员 的名称、限定符和参数等。有了反射,即可对每一个类型了如指掌。如果获得了构造函数的信息,即可直接创建对象,即使这个对象的类型在 编译时还不知道。

1.1 .NET可执行应用程序结构 
        程序代码在编译后生成 可执行的应用,我们首先要了解这种可执行应用程序的结构。 
        应用程序结构分为应 用程序域—程序集—模块—类型—成员几个层次,公共语言运行库加载器管理应用程序域,这种管理包括将每个程序集加载到相应的应用程序 域以及控制每个程序集中类型层次结构的内存布局。 
        程序集包含模块,而模块包含 类型,类型又包含成员,反射则提供了封装程序集、模块和类型的对象。我们可以使用反射动态地创建类型的实例,将类型绑定到现有对象或 从现有对象中获取类型,然后调用类型的方法或访问其字段和属性。反射通常具有以下用途。
(1)使用Assembly定义和加载程序集,加 载在程序集清单中列出模块,以及从此程序集中查找类型并创建该类型的实例。
(2)使用Module了解包含模块的程序集以及模块中的类 等,还可以获取在模块上定义的所有全局方法或其他特定的非全局方法。
(3)使用ConstructorInfo了解构造函数的名称、参数、访问修 饰符(如pulic 或private)和实现详细信息(如abstract或virtual)等。使用Type的GetConstructors或GetConstructor方法来调用特定的构 造函数。
(4)使用MethodInfo了解方法的名称、返回类型、参数、访问修饰符(如pulic 或private)和实现详细信息(如abstract或 virtual)等。使用Type的GetMethods或GetMethod方法来调用特定的方法。
(5)使用FiedInfo了解字段的名称、访问修饰符(如public 或private)和实现详细信息(如static)等,并获取或设置字段值。
(6)使用EventInfo了解事件的名称、事件处理程序数据类型、自 定义属性、声明类型和反射类型等,添加或移除事件处理程序。
(7)使用PropertyInfo了解属性的名称、数据类型、声明类型、反射类 型和只读或可写状态等,获取或设置属性值。
(8)使用ParameterInfo了解参数的名称、数据类型、是输入参数还是输出参数,以及参数 在方法签名中的位置等。 
        System.Reflection.Emit命名空间的类提供了一种特殊形 式的反射,可以在运行时构造类型。 
        反射也可用于创建称为类型浏览器的应用程序 ,使用户能够选择类型,然后查看有关选定类型的信息。 
        此外,Jscript等语言编 译器使用反射来构造符号表。System.Runtime.Serialization命名空间中的类使用反射来访问数据并确定要永久保存的字段, System.Runtime.Remoting命名空间中的类通过序列化来间接地使用反射。

1.2 反射技术示例  
        下面是反射技术的示例,我们可以在程序去得时动态实例化对象,获得对象的属性 ,并调用对象的方法。
 1Namespace ReflectionExample
 2{
 3  class Class1
 4  {
 5      [STAThread]
 6      static void Main (string [ ] args)
 7      {
 8          System.Console.WriteLine(“列出程序集中的所有类型 ”);
 9          Assembly a = Assembly.LoadFrom (“ReflectionExample.exe”);
10          Type[ ] mytypes = a.GetTypes( );
11
12          Foreach (Type t in mytypes)
13          {
14              System.Console.WriteLine (  t.Name );
15          }

16          System.Console.ReadLine ( );
17      System.Console.WriteLine (“列出HellWord中的所有方法 ” );
18      Type ht = typeof(HelloWorld);
19      MethodInfo[] mif = ht.GetMethods();
20      foreach(MethodInfo mf in mif)
21      {
22          System.Console.WriteLine(mf.Name);
23      }

24      System.Console.ReadLine();
25      System.Console.WriteLine("实例化HelloWorld,并调用SayHello方法");
26      Object obj = Activator.CreateInstance(ht);
27      string[] s = {"zhenlei"};
28      Object bojName = Activator.CreateInstance(ht,s);
29      BindingFlags flags = (BindingFlags.NonPublic|BindingFlags.Public|BindingFlags.Static|BindingFlags.Instance|BindingFlags.DeclaredOnly);
30      MethodInfo msayhello = ht.GetMethod("SayHello");
31      msayhello.Invoke(obj,null);
32      msayhello.Invoke(objName,null);
33      System.Console.ReadLine();
34    }

35    }

36}

 1using System;
 2namespace ReflectionExample
 3{
 4    public class HelloWorld
 5    {
 6        string myName = null;
 7        public HelloWorld(string name)
 8        {
 9            myName = name;
10        }

11        public HelloWorld() : this(null)
12        {}
13        public string Name
14        {
15            get
16            {
17                return myName;
18            }

19        }

20        public void SayHello()
21        {
22            if(myName == null)
23            {
24                System.Console.Writ eLine("Hello World");
25            }

26            else
27            {
28                System.Console.Writ eLine("Hello," + myName);
29            }

30        }

31    }

32}

33

1.3 在设计模式实现中使用反射技术  
        采用反射技术可以简化工厂的实现。
(1)工厂方法:通过反射可以将需要实现的子类名称传递给工厂方法 ,这样无须在子类中实现类的实例化。
(2)抽象工厂 :使用反射可以减少抽象工厂的子类。 
        采用反射技术可以简化工厂代码的复杂程度 ,在.NET项目中,采用反射技术的工厂已经基本代替了工厂方法。 
        采用反射技术可 以极大地简化对象的生成,对以下设计模式的实现也有很大影响。
(1)命令模式:可以采用命令的类型名称作为参数直接获得命令的实 例,并且可以动态执行命令。
(2)享元模式:采用反射技术实例化享元可以简化享元工厂。

2 委托技术与设计模式
        委托技术是.NET引入的一种 重要技术,使用委托可以实现对象行为的动态绑定,从而提高设计的灵活性。

2.1 .NET中的委托技术
        .NET运行库支持称为“委托”的引用类型,其作用类似于C++中的函数指针。 与函数指针不同,委托实例独立于其封装方法的类,主要是那些方法与委托类型兼容。另外,函数指针只能引用静态函数,而委托可以引用静 态和实例方法。委托主要用于.NET Framework中的事件处理程序和回调函数。
        所有委托都 从System.Delegate继承而来并且有一个调用列表,这是在调用委托时所执行方法的一个链接列表。产生的委托可以用匹配的签名引用任何方法 ,没有为具有返回类型并在调用列表中包含多个方法的委托定义返回值。
        可以使用的委托 Cimbine及Remove方法在其调用列表中添加和移除方法。若要调用委托,可使用Invoke方法,或者使用BeginInvoke和EndInvoke方法异步调用委 托。委托类的实现由运行库提供,而不由用户代码提供。
        委托适用于那种在某些语言中需 要用函数指针来解决的情况,但是与函数指针不同,它是面向对象和类型安全的。
        委托声 明定义一个类,它是从System.Delegate类派生的类。委托实例封装了一个调用列表,其中列出了一个或多个方法,每个方法称为一个可调用实 体。对于实例方法,可调用实体由一个实例和该实例的方法组成;对于静态方法,可调用实体仅由一个方法组成。如果用一组合适的参数来调 用一个委托实例,则该委托实例所封装的每个可调用实体都会被调用,并且使用上述同一组参数。
        委托实例的一个有用的属性是它既不知道,也不关心其封装方法所属类的详细信息,对它 来说最重要的是这些方法与该委托的类型兼容。即只要方法的返回类型和参数表是相同的,则方法与委托类型兼容,方法的名称不一定要与委 托类相同。
定义和使用委托分为声明、实例化和调用3个步骤。委托用委托声明语法声明,如:
    delegate void myDelegate( );
声明一个名为myDelegate的委托,它不带参数并且不返回任何结果,如:
class Test
{
       static void F( ) 
      {
              System.Console.WriteLine (“Test.F”);
      }
       static void Main ( )  
      {
            myeDelegate d = new myDelegate (F);
            d ( );
      }
}
创建一个myDelegate实例,然后立即调用它。这样做并没有太大的意义,因为直接 调用方法会更简单。当涉及其匿名特性时,委托才能真正显示出其效果,如:
    void MultiCall (myDelegate d, int count )  {
      for  (int I = 0; I < count; I++)  {
        d( );
      }
    }
显示一个 重复调用 myDelegate的MultiCall 方法,这个方法不知道,也不必知道myDelegate的目标方法的类型、该方法具有的可访问性或者是否为静态 。对它来说最重要的是目标方法与myDelegate兼容。

2.2示例
        下面的例子说明了 委托的实现,代码如下:
 1using System;
 2namespace DelegateExample
 3{
 4    public class TemplateMethod
 5    {
 6        public delegate float Comp(float a,float b);
 7        public Comp myComp;
 8        public TemplateMethod()
 9        {}
10        public float DoComp(float[] f)
11        {
12            float nf = float.NaN;
13            foreach(float df in f)
14            {
15                if(float.IsNaN(nf))
16                   & nbsp;nf = df;
17                else
18                   & nbsp;nf = myComp(nf,df);
19            }

20            return nf;
21        }

22
23    }

24}

2.3 委托技术与GOF设计模式中委 托的关系
        需要指出的是,.NET中的委托技术与GOF在《设计模式》中所提列的委托的意图 一致,但在实现方法上有相当大的区别。.NET中的委托更进一步地降低了对象间的耦合性,将静态的组合关系变为运行时的动态组合关系。
        GOF在《设计模式》中定义的委托是:“委托是一种组合方法,它使组合具有与继承 同样的复用能力。在委托方式下,有两个对象参与处理一个请求,接受请求的对象将操作委托给它的代理者(delegate),它类似于子类将请 求交给它的父类处理。使用继承时,被继承的操作总能引用接受请求的对象。在C++中通过this成员变量,在Smalltalk中则通过self。委托方 式为了得到同样的效果,接受请求的对象将自身传给被委托者(代理人),使被委托的操作可以引用接受请求的对象。 ”
        如果采用.NET的委托技术,上述结构可以更加灵活。Window不引用Rectangle即可 实现Area的计算,为此首先声明一个计算面积的委托定义,示例代码如下:
    public delegate float Darea();
然 而在Window类中声明与这个代理一致的接口:
    class Window
    { 
        public Darea Area;
    }
这里不需要引用Rectangle类,只是 在执行时动态绑定即可:
Rectangle rc = new Rectangle();
Window w = new Window();
w.Area = new Darea(rc.Area);
        这样当调用w的Area时,实际调用的是Reactangel的Area方法。从实现意 图上看,.NET的委托更好地实现了GOF所阐述的意图,结构上也更为灵活。但这两种委托解决的不是一个层面的问题,GOF的委托强调的是一种 策略,而.NET和委托技术则是具体实现。

2.4 委托技术与设计模式实现
        采用委托 技术可以进一步实现用组合代替继承的思路,很多采用继承实现的关系可以采用委托实现。采用委托可以简化下列设计模式的使用。
(1) 模板方法:这种方法采用继承实现具体方法,采用委托可以动态实现方法的组合。
(2)观察者:可以使用事件委托实现观察者与主题之间 的通信。
(3)中介者:使用委托可以去除工件与中介者之间的耦合关系。

相关文章推荐

.NET反射、委托技术与设计模式

  • 2010年03月05日 10:05
  • 42KB
  • 下载

论.NET反射、委托技术与设计模式关系

http://www.cnblogs.com/lemon0017/archive/2008/11/13/1332900.html 论.NET反射、委托技术与设计模式关系 反射技...

.Net 委托技术与设计模式

委托技术是。NET引入的一种重要技术,使用委托可以实现对象行为的动态绑定,从而提高设计的灵活性。   2.1 .NET中的委托技术   。NET运行库支持称为“委托”的引用类型,其作用类似于C++...

.Net反射工厂设计模式

1.概述         如果采用传统方式实现了简单工厂、工厂方法和抽象工厂在有些场合下如此处理,代码会变得冗余并且难以维护。         假设我们需要创建一种交通工具,可以是汽车、火车或者轮...

Asp.net环境下经典MVC设计模式

  • 2011年02月26日 18:26
  • 152KB
  • 下载

.NET设计模式(3): 抽象工厂

抽象工厂模式(Abstract Factory Pattern) 引入: 在前面介绍的两个创建型模式里面,我们解决的都是有关"new"的问题,用它们来避免显式指定类创建对象。我写的也非常简单易...

ASP.NET 中的设计模式之MVC篇

  • 2007年08月31日 15:00
  • 40KB
  • 下载

.NET中的设计模式

  • 2009年04月01日 09:25
  • 1.11MB
  • 下载

15. .NET与设计模式

在大型软件架构中,设计模式可谓无处不在;在.NET Framework架构中,设计模式同样广泛应用在各个部分的设计之中。那么,什么是设计模式呢? 设计模式 是一系列的解决方案,它们被用于特定的环境来...
  • chydev
  • chydev
  • 2012年07月18日 10:35
  • 288
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:.NET反射、委托技术与设计模式
举报原因:
原因补充:

(最多只允许输入30个字)