分享
 
 
 

动态装载和使用类型

王朝厨房·作者佚名  2007-01-04
窄屏简体版  字體: |||超大  

Reflection提供诸如Microsoft Visual Basic.NET和JScript语言编译器使用的底层结构来实施隐性后绑定。绑定是定位与某一特定类型相对应的声明的过程。当这个过程发生在运行的时候,而不是编译的时候,它被称为后绑定。Visual Basic.NET使你可以在你的代码中使用隐性后绑定;VisualBasic.NET编译器调用helper 方法,使用Reflection获得对象类型。传递给helper 方法的参数 使适当的方法可以在运行时被调用。这些参数是调用方法(对象)的实例,被调用方法的名字(字符串),及传递给被调用方法的参数。(一个对象数组)。

在以下代码例子中, Visual Basic.NET编译器通过Reflection隐性地 来对一在编译时不知类型的对象调用方法。HelloWorld 类有一种 PrintHello 方法,可以打印出 "Hello World" 及传递给PrintHello 方法的一些文本。本例中PrintHello 方法 调用实际上是Type. InvokeMember ; Visual Basic 代码 允许PrintHello 方法被调用,仿佛 对象的类型 (helloObj)在编译时就已经知道了(前期绑定),而不是在运行时(后绑定)。

[Visual Basic]

Imports System

Module Hello

Sub Main()

’ Set up variable.

Dim helloObj As Object

’ Create the object.

helloObj = new HelloWorld()

’ Invoke the print method as if it was early bound

’ even though it’s really late bound.

helloObj.PrintHello("Visual Basic Late Bound")

End Sub

End Module

自定义绑定

Reflection除了可以隐性地被编译器用于后绑定,也可以在代码中显示使用,来完成后绑定。

common language runtime 支持多种编程语言,这些语言的绑定规则互不相同。在前绑定的情况下,代码生成器能完全控制绑定。然而,在使用Reflection的后绑定中,绑定必须由自定义绑定控制。Binder类提供成员选择与调用的自定义控制。

使用自定义绑定, 您可以在运行时装载assembly,获得assembly中关于类型的信息,指明您索要的类型,并且调用方法,访问字段,或类型的属性。如果在编译时您不知道对象的类型,该技术就显得格外有用,比如,当对象类型依赖于用户输入时。以下例子中的代码显示了在HelloWorld.dll assembly 中,被动态使用Reflection调用的方法,第一个在Visual Basic.NET,第二个在C#中。

[Visual Basic]

’ This class is deployed as an assembly consisting Hello World string.

Private m_helloWorld As String = "HelloWorld"

’ Default public constructor.

Public Sub New()

End Sub ’New

’ Print "Hello World" plus thepassed text.

Public Sub PrintHello(txt As String)

’ Output to the Console.

Console.WriteLine((m_helloWorld & "" & txt))

End Sub

End Class

Imports System

Imports System.Reflection

Module VisualBasicLateHello

Sub Main()

’ Set up the variables.

Dim assem as System.Reflection.Assembly

Dim obj as Object

Dim helloType as Type

Dim printMethod as MethodInfo

’ Load the assembly to use.

assem = System.Reflection.Assembly.Load("HelloWorld")

’ Get the type to use from the assembly.

helloType = assem.GetType("HelloWorld")

’ Get the method to use from the type.

printMethod = helloType.GetMethod("PrintHello")

’ Create an instance of the type.

obj = Activator.CreateInstance(helloType)

’ Create an array to hold the arguments.

Dim args(1) as Object

’ Set the arguments.

args(0) = "From Visual Basic Late Bound"

’ Invoke the method.

printMethod.Invoke(obj, args)

End Sub

End Module

以下为C# 版:

[C#]

// This class is deployed as an assembly consisting of one DLL,

// called HelloWorld.dll.

using System;

public class HelloWorld {

// Constant Hello World string.

private const String m_helloWorld = "Hello World";

// Default public constructor.

public HelloWorld() {

}

// Print "Hello World" plus the passed text.

public void PrintHello(String txt) {

// Output to the Console.

Console.WriteLine(m_helloWorld + " " + txt);

}

}

// Illustrates reflection’s late binding functionality.

// Calls the PrintHello method on a dynamically loaded

// and created instance of the HelloWorld class.

using System;

using System.Reflection;

public class CSharpLateHello {

public static void Main() {

// Load the assembly to use.

Assembly assem = Assembly.Load("HelloWorld");

// Get the type to use from the assembly.

Type helloType = assem.GetType("HelloWorld");

// Get the method to call from the type.

MethodInfo printMethod = helloType.GetMethod("PrintHello");

// Create an instance of the HelloWorld class.

Object obj = Activator.CreateInstance(helloType);

// Create the args array.

Object[] args = new Object[1];

// Set the arguments.

args[0] = "From CSharp Late Bound";

// Invoke the PrintHello method.

printMethod.Invoke(obj, args);

}

}

InvokeMember 与 CreateInstance

可以使用Type.InvokeMember来调用某类型成员。各种类的CreateInstance 方法,例如System.Activator 和 System.Reflection.Assembly,是InvokeMember的专用形式,用于生成某类型新的实例。Binder类在这些方法中,被用于重载解析和参数转换。

以下例子中的代码显示了三种可能的参数转换及成员选择的组合。在Case1中, 不需要参数转换或成员选择。在Case 2中,只需要成员选择。在Case3中, 只需要参数转换。

[C#]

public class CustomBinderDriver

{

public static void Main (string[] arguments)

{

Type t = typeof (CustomBinderDriver);

CustomBinder binder = new CustomBinder();

BindingFlags flags = BindingFlags.InvokeMethod|BindingFlags.Instance|

BindingFlags.Public|BindingFlags.Static;

//Case 1. Neither argument coercion nor memberselection is needed.

args = new Object[] {};

t.InvokeMember ("PrintBob", flags,binder, null, args);

//Case 2. Only member selection is needed.

args = new Object[] {42};

t.InvokeMember ("PrintValue", flags,binder, null, args);

//Case 3. Only argument coercion is needed.

args = new Object[] {"5.5"};

t.InvokeMember ("PrintNumber",flags, binder, null, args);

}

public static void PrintBob ()

{

Console.WriteLine ("PrintBob");

}

public static void PrintValue (long value)

{

Console.WriteLine ("PrintValue ({0})",value);

}

public static void PrintValue (String value)

{

Console.WriteLine ("PrintValue\"{0}\")",value);

}

public static void PrintNumber (double value)

{

Console.WriteLine ("PrintNumber ({0})",value);

}

}

当存在多于一个的同名成员时,就需要有重载解析。Binder.BindToMethod 和Binder.BindToField 方法可以用来绑定到一个成员。Binder.BindToMethod也可以通过get 和set 属性访问器提供属性解析。

BindToMethod 返回可被调用的MethodBase. 如无可用的调用则返回null. 如果无法调用,BindToMethod 返回 MethodBase 为 调用或 null。MethodBase返回值无需是match参数之一,尽管事实往往如此。

调用者 也许会想得到ByRef 参数的返回。所以,如果BindTo方法改动过参数数组,Binder 允许客户使参数数组映射回它原来的表格。为了实现这点,调用者必须确保参数顺序不变。当参数由名字传递,Binder重新整理参数组,以供调用者察看。

可用成员是指那些在类型或任何基本类型中定义的那些成员。如果指明BindingFlags.NonPublic,任何访问级别的成员都会在返回中。如果BindingFlags.NonPublic 没有被指明,binder必须执行访问规则。当指明Public或 NonPublic 绑定标志, 你必须也指明Instance 或Static 标志, 否则不会有成员返回。

如果只有一个成员与名字对应,就不需要回调,也就完成到这个方法的绑定。Case 1 中的代码例子表明了这一点:只有一个可用的PrintBob 方法, 所以,不需要回调。

如在可用集中,有多于一个成员。所有这些方法被传递给BindTo方法, 再由它选择适当的方法,并且返回。在 Case 2 中的代码例子中,有两种叫做PrintValue的方法。合适的方法取决于对BindToMethod调用。

ChangeType 执行参数转换, 它把实际参数转变为选定方法的参数类型。即使类型已经完美匹配,ChangeType也会针对每个参数被调用。

在 Case 3 中的代码例子中, 值为"5.5"的String类型的一个实际参数以正式参数Double类型被传递给方法。要想调用成功,字符串值"5.5"必须被转变为一个double值。ChangeType 执行了这种转变。

ChangeType 仅执行无损失转换, 如下表所示:

Source Type Target Type

Any type Its base type

Any type Interface it implements

Char UInt16, UInt32, Int32, UInt64, Int64, Single, Double

Byte Char, UInt16, Int16, UInt32, Int32, UInt64, Int64, Single, Double

SByte Int16, Int32, Int64, Single, Double

UInt16 UInt32, Int32, UInt64, Int64, Single, Double

Int16 Int32, Int64, Single, Double

UInt32 UInt64, Int64, Single, Double

Int32 Int64, Single, Double

UInt64 Single, Double

Int64 Single, Double

Single Double

Non-reference type Reference type

Type类有Get方法,可使用Binder类型的参数的来解析对某成员的引用。Type.GetConstructor,Type. GetMethod , 和 Type.GetProperty 通过提供某成员的签名信息来查找该成员。它们调用Binder.SelectMethod和Binder.SelectProperty 以选择适合方法的签名信息。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有