Your Ad Here
首页 | 编程语言 | 网站建设 | 游戏天堂 | 冲浪宝典 | 网络安全 | 操作系统 | 软件时空 | 硬件指南 | 病毒相关 | IT 认证
软讯网络 > 网站建设 > ASP.NET > (Reflection)认识反射(反射实例化,反射评价,在工厂三层架构应用)
【标  题】:(Reflection)认识反射(反射实例化,反射评价,在工厂三层架构应用)
【关键字】:Reflection
【来  源】:http://blog.csdn.net/gkq8124372/archive/2007/04/11/1560178.aspx

(Reflection)认识反射(反射实例化,反射评价,在工厂三层架构应用)

Your Ad Here

反射的基础概念:

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

  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了解参数的名称、数据类型、是输入参数还是输出参数,以及参数在方法签名中的位置等。

  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) //循环所有类型Type

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) //循环所有方法MethodInfo[]

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); // 实例化CreateInstance

29  BindingFlags flags = (BindingFlags.NonPublic|BindingFlags.Public|BindingFlags.Static|BindingFlags.Instance|BindingFlags.DeclaredOnly);

30  MethodInfo msayhello = ht.GetMethod("SayHello");

31  msayhello.Invoke(obj,null); //调用方法Invoke

32  msayhello.Invoke(objName,null);

33  System.Console.ReadLine();

34  }

35 }

36}

1using System; //被使用的Dll

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.WriteLine("Hello World");

25    }

26    else

27    {

28     System.Console.WriteLine("Hello," + myName);

29    }

30   }

31  }

32}

33 

实例2

用反射调用任意.net库中的方法(函数中含详尽解述)

 

函数如下:ReturnMessage自定议类

2、通过NameSpaceAndClassNameMethodName实际上就可以精确定位一个方法了如调用abc.dll里的namespace1.Class1.Main,调用起来就是CallAssembly("abc.dll","namespace1.Class1","Main",null)

 

public static ReturnMessage CallAssembly(string Path,string NameSpaceAndClassName,string MethodName,object[] Parameters)

{

       try

       {

          Assembly Ass=Assembly.LoadFrom(Path);//调入文件(不限于dll,exe亦可,只要是.net)

          Type TP=Ass.GetType(NameSpaceAndClassName);//NameSpaceAndClassName"名字空间.类名","namespace1.Class1"

          MethodInfo MI=TP.GetMethod(MethodName);//MethodName是要调用的方法名,"Main"

          object MeObj=System.Activator.CreateInstance(TP);

          MI.Invoke(MeObj,Parameters);//Parameters是调用目标方法时传入的参数列表

          return new ReturnMessage(true,"成功调用",1);

        }

       catch(Exception e)

        {

          return new ReturnMessage(false,"出现异常,消息为:"+e.Message,-1,e);

        }

    }

 

实例3

(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);//通过反射获取dll类型

            }

 //使用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

 

 

( 3 ) 简单谈谈反射工厂

        借网上一个实例,在此再简单论述一下反射在工厂三层中的应用,以作深一步理解使用反射。
        例:假设我们需要创建一种交通工具,可以是汽车、火车或者轮船。

         采用简单工厂方法来实现,代码如下:
采用接口定义了抽象的工厂方法

public Interface CreateVehicleInterface CreateVehicle 定义一个产生交通工具的接口
     Function CreateAVehicle()Function CreateAVehicle() As Vehicle `创建一个交通工具
End Interface
具体的创建由子类决定
public