Dynamicmethod 类(位于System.Reflection.Emit名空间下),用于定义并表示一种可编译、执行和
丢弃的动态方法。
而下面是微软对于Dynamicmethod的应用及其运行情况的介绍:
可以使用 Dynamicmethod 类在运行时生成和执行方法,而不必生成动态程序集和动态类型来包含该方
法。回收 Dynamicmethod 对象时,由实时 (JIT) 编译器创建的可执行代码也将回收。动态方法是生成和
执行少量代码的最有效方式。
动态方法在逻辑上与模块或类型关联。如果与模块关联,动态方法对于该模块在全局范围内有效。如果有
足够的权限,动态方法可以跳过 JIT 编译器的可见性检查,访问具有该模块所声明类型的私有数据。可以将
动态方法与任何模块关联,无论该模块是否由您创建。
如果动态方法与类型关联,动态方法可以访问该类型的私有成员。除非动态方法需要访问在同一模块中声
明的其他类型的私有数据,否则无需跳过 JIT 可见性检查。可以将动态方法与任何类型关联。
下表显示了动态方法与模块关联或与模块中的类型关联时,在进行以及不进行 JIT 可见性检查的情况下,
动态方法可以在模块中访问的类型成员。
动态方法对所关联的模块或包含所关联的类型的模块具有权限。
无需对动态方法及其参数进行命名,但是可以指定名称以协助调试(下文中将会介绍)。动态方法或其属性
不支持自定义属性。
丢弃的动态方法。
而下面是微软对于Dynamicmethod的应用及其运行情况的介绍:
可以使用 Dynamicmethod 类在运行时生成和执行方法,而不必生成动态程序集和动态类型来包含该方
法。回收 Dynamicmethod 对象时,由实时 (JIT) 编译器创建的可执行代码也将回收。动态方法是生成和
执行少量代码的最有效方式。
动态方法在逻辑上与模块或类型关联。如果与模块关联,动态方法对于该模块在全局范围内有效。如果有
足够的权限,动态方法可以跳过 JIT 编译器的可见性检查,访问具有该模块所声明类型的私有数据。可以将
动态方法与任何模块关联,无论该模块是否由您创建。
如果动态方法与类型关联,动态方法可以访问该类型的私有成员。除非动态方法需要访问在同一模块中声
明的其他类型的私有数据,否则无需跳过 JIT 可见性检查。可以将动态方法与任何类型关联。
下表显示了动态方法与模块关联或与模块中的类型关联时,在进行以及不进行 JIT 可见性检查的情况下,
动态方法可以在模块中访问的类型成员。
动态方法对所关联的模块或包含所关联的类型的模块具有权限。
无需对动态方法及其参数进行命名,但是可以指定名称以协助调试(下文中将会介绍)。动态方法或其属性
不支持自定义属性。
这么一大块看下来,头肯定大了,而本文的例子确很简单,因为DEMO的主要代码全部取自Silverlight2 Beta2
CHM,本人也只是将其中的代码修饰一下并将主要的注释翻译了过来,希望能通过注释让大家明白动态方法到底如
何写,如何用.当然因为Dynamicmethod这个类的构造方法被重载了六次,而CHM中所介绍的也只是它的基本构造
方法,形如:
CHM,本人也只是将其中的代码修饰一下并将主要的注释翻译了过来,希望能通过注释让大家明白动态方法到底如
何写,如何用.当然因为Dynamicmethod这个类的构造方法被重载了六次,而CHM中所介绍的也只是它的基本构造
方法,形如:
using
System;
System.Reflection;
System.Reflection.Emit;
System.Runtime.InteropServices;
public class Example
{
// 下面的构造函数和公有属性用于将动态方法绑定到对象实例时使用
int Test;
Example( test)
{
this .Test = test;
}
下面的代理(delegate)用于调用动态方法 private delegate long Square( input);
Bound( Unbound(Example target, input);
/// <summary>
动态方法简单调用
</summary> <param name="outputBlock"></param>
static void Demo1(System.Windows.Controls.TextBlock outputBlock)
{
outputBlock.Text += " 例子 1 : 动态方法简单调用\n\n " ;
例子 1: 简单的动态方法
创建一个动态方法所使用的参数类型数组,因为当前例子中只有一个参数(int 类型),所
以数组中将会只有一个类型 Type[] methodArgs { typeof ( ) };
创建一个动态方法(Dynamicmethod)。
在这个例子中, 方法名称为SquareIt(平方运算).
另外,动态方法名称不是必填项. 因为系统不会按方法名称来调用动态方法(而是采用delegate).
还有就是两个动态方法可以使用同一个方法名称.不过,这个方法名称会在调用堆栈(calls stacks)
中出现,这样便于进行调试
在这个例中,动态方法的返回类型是Long [如下typeof(long)]. System.Reflection.Emit.Dynamicmethod squareIt new System.Reflection.Emit.Dynamicmethod(
SquareIt ,
),
methodArgs
);
下面是SquareIt(平方运算)的函数内容.
生成 MSIL(MS中间语言).
Dynamicmethod has an associated type DynamicILInfo that can be used in conjunction with
unmanaged code generators.
MSIL 加载该参数(Integer)到堆栈上 , 并将其转换成为Long 类型. duplicates(复制) 栈顶元素.
然后将栈顶的两个元素的乘积(平方运算)压入堆栈(返回结果时使用) ILGenerator il squareIt.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Conv_I8);
il.Emit(OpCodes.Dup);
il.Emit(OpCodes.Mul);
il.Emit(OpCodes.Ret);
为上面的方法创建一个代码并将其绑定到Square的实例上.
Creating the delegate completes the method, and any further
attempts to change the method (for example, by adding more
MSIL) are ignored.
//
Square invokeSquareIt
(Square)squareIt.CreateDelegate( (Square));
下面的代码显示了如使用 Square delegate,
outputBlock.Text String.Format( 123456789 squared = {0}\n 123456789 ));
当然绑定代理也可以使用 Func (能生成带单一参数且有返回类型的泛型代理),如下: Func < > invokeGeneric
(Func )squareIt.CreateDelegate( (Func ));
outputBlock.Text 987654321 squared = {0}\n 987654321 ));
}
对象实例绑定调用
Demo2(System.Windows.Controls.TextBlock outputBlock)
{
outputBlock.Text \n例子 2: 对象实例绑定调用\n\n 例子 2: 将动态方法绑定到实例上.
下面语句将会创建一个指定参数类型的数组,以便将其绑定的动态方法上
如要将方法(method)代理绑定到对象上,那么第一个参数应匹配代理要绑定的对象类型
在下面代码中,要绑定的是Example类型的对象 Type[] methodArgs2 (Example),0);"> 创建动态方法, 在这个例子中, 该(动态)方法没有指定名称(为""),
返回值类型为Integer. 这个方法将会访问Example类的公有成员(Test)
System.Reflection.Emit.Dynamicmethod multiplyTestField "" MSIL 加载第一个参数(Example类的一个实例), 然后使用这个实例来访问公有成员(Test) ILGenerator ilMP multiplyTestField.GetILGenerator();
ilMP.Emit(OpCodes.Ldarg_0);
FieldInfo testInfo (Example).GetField( Test | BindingFlags.Instance);
加载第二个参数, 然后这两个数字会被相乘,如果返回值比INT大,则会执行截取操作,并将结果返回. ilMP.Emit(OpCodes.Ldfld, testInfo);
ilMP.Emit(OpCodes.Ldarg_1);
ilMP.Emit(OpCodes.Mul);
ilMP.Emit(OpCodes.Ret);
#region Bound1
创建上面动态方法的代理.
attempts to change the method for example,0);"> MSIL are ignored.
下面代码会将上面的动态方法绑定到Example 类的一个新实例上,同时将该实例的Test属性设置成42.
这样每次代理运行时,都会调用同一个Example实例.另外这个代理将不再使用类型Example作为参数,
因为Example的实例已绑定到了代理的Target参数上(如下面的((Example)invoke.Target).Test调用)
因为下面的方法调用就像是隐藏了方法的第一个参数一样.
下面代理被执行了两次,分别使用了不同的参数值(分别为3, 5) Bound invoke (Bound)multiplyTestField.CreateDelegate(
(Bound),0);"> Example( 42 String.Format(
Example.Test = {0}; {1} * Example.Test = {2}\n 3 ));
outputBlock.Text 5 修改当前实例的Test字段(42*2=84) ((Example)invoke.Target).Test *= 2 ;
outputBlock.Text Example.Test = {0}; {1} * Example.Test = {2}\n\n #endregion Bound2 下面的Example实例将会被绑定到一个Bound代理上, 然后这个代理会运行两次,0);"> 其间对 Example的Test值进行加1操作(类似上面的*2操作) Example ex 5280 );
Bound another
(Bound)multiplyTestField.CreateDelegate( ex.Test, another( ));
ex.Test 1
Unbound 最后,创建一个类型Unbound的代理.而它有两个参数,一个是Example的实例,另一个是一个Integer型数据.
下面的代理(Unbound) 将会绑定不带Example实例的方法,实相应的实例参数将会在代理执行过程中进行加载 Unbound notBound
(Unbound)multiplyTestField.CreateDelegate( (Unbound));
outputBlock.Text {0} * Example.Test(42) = {1}\n 10 {0} * Example.Test(56) = {1}\n 56
}
}
System.Reflection;
System.Reflection.Emit;
System.Runtime.InteropServices;
public class Example
{
// 下面的构造函数和公有属性用于将动态方法绑定到对象实例时使用
int Test;
Example( test)
{
this .Test = test;
}
下面的代理(delegate)用于调用动态方法 private delegate long Square( input);
Bound( Unbound(Example target, input);
/// <summary>
动态方法简单调用
</summary> <param name="outputBlock"></param>
static void Demo1(System.Windows.Controls.TextBlock outputBlock)
{
outputBlock.Text += " 例子 1 : 动态方法简单调用\n\n " ;
例子 1: 简单的动态方法
创建一个动态方法所使用的参数类型数组,因为当前例子中只有一个参数(int 类型),所
以数组中将会只有一个类型 Type[] methodArgs { typeof ( ) };
创建一个动态方法(Dynamicmethod)。
在这个例子中, 方法名称为SquareIt(平方运算).
另外,动态方法名称不是必填项. 因为系统不会按方法名称来调用动态方法(而是采用delegate).
还有就是两个动态方法可以使用同一个方法名称.不过,这个方法名称会在调用堆栈(calls stacks)
中出现,这样便于进行调试
在这个例中,动态方法的返回类型是Long [如下typeof(long)]. System.Reflection.Emit.Dynamicmethod squareIt new System.Reflection.Emit.Dynamicmethod(
SquareIt ,
),
methodArgs
);
下面是SquareIt(平方运算)的函数内容.
生成 MSIL(MS中间语言).
Dynamicmethod has an associated type DynamicILInfo that can be used in conjunction with
unmanaged code generators.
MSIL 加载该参数(Integer)到堆栈上 , 并将其转换成为Long 类型. duplicates(复制) 栈顶元素.
然后将栈顶的两个元素的乘积(平方运算)压入堆栈(返回结果时使用) ILGenerator il squareIt.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Conv_I8);
il.Emit(OpCodes.Dup);
il.Emit(OpCodes.Mul);
il.Emit(OpCodes.Ret);
为上面的方法创建一个代码并将其绑定到Square的实例上.
Creating the delegate completes the method, and any further
attempts to change the method (for example, by adding more
MSIL) are ignored.
//
Square invokeSquareIt
(Square)squareIt.CreateDelegate( (Square));
下面的代码显示了如使用 Square delegate,
outputBlock.Text String.Format( 123456789 squared = {0}\n 123456789 ));
当然绑定代理也可以使用 Func (能生成带单一参数且有返回类型的泛型代理),如下: Func < > invokeGeneric
(Func )squareIt.CreateDelegate( (Func ));
outputBlock.Text 987654321 squared = {0}\n 987654321 ));
}
对象实例绑定调用
Demo2(System.Windows.Controls.TextBlock outputBlock)
{
outputBlock.Text \n例子 2: 对象实例绑定调用\n\n 例子 2: 将动态方法绑定到实例上.
下面语句将会创建一个指定参数类型的数组,以便将其绑定的动态方法上
如要将方法(method)代理绑定到对象上,那么第一个参数应匹配代理要绑定的对象类型
在下面代码中,要绑定的是Example类型的对象 Type[] methodArgs2 (Example),0);"> 创建动态方法, 在这个例子中, 该(动态)方法没有指定名称(为""),
返回值类型为Integer. 这个方法将会访问Example类的公有成员(Test)
System.Reflection.Emit.Dynamicmethod multiplyTestField "" MSIL 加载第一个参数(Example类的一个实例), 然后使用这个实例来访问公有成员(Test) ILGenerator ilMP multiplyTestField.GetILGenerator();
ilMP.Emit(OpCodes.Ldarg_0);
FieldInfo testInfo (Example).GetField( Test | BindingFlags.Instance);
加载第二个参数, 然后这两个数字会被相乘,如果返回值比INT大,则会执行截取操作,并将结果返回. ilMP.Emit(OpCodes.Ldfld, testInfo);
ilMP.Emit(OpCodes.Ldarg_1);
ilMP.Emit(OpCodes.Mul);
ilMP.Emit(OpCodes.Ret);
#region Bound1
创建上面动态方法的代理.
attempts to change the method for example,0);"> MSIL are ignored.
下面代码会将上面的动态方法绑定到Example 类的一个新实例上,同时将该实例的Test属性设置成42.
这样每次代理运行时,都会调用同一个Example实例.另外这个代理将不再使用类型Example作为参数,
因为Example的实例已绑定到了代理的Target参数上(如下面的((Example)invoke.Target).Test调用)
因为下面的方法调用就像是隐藏了方法的第一个参数一样.
下面代理被执行了两次,分别使用了不同的参数值(分别为3, 5) Bound invoke (Bound)multiplyTestField.CreateDelegate(
(Bound),0);"> Example( 42 String.Format(
Example.Test = {0}; {1} * Example.Test = {2}\n 3 ));
outputBlock.Text 5 修改当前实例的Test字段(42*2=84) ((Example)invoke.Target).Test *= 2 ;
outputBlock.Text Example.Test = {0}; {1} * Example.Test = {2}\n\n #endregion Bound2 下面的Example实例将会被绑定到一个Bound代理上, 然后这个代理会运行两次,0);"> 其间对 Example的Test值进行加1操作(类似上面的*2操作) Example ex 5280 );
Bound another
(Bound)multiplyTestField.CreateDelegate( ex.Test, another( ));
ex.Test 1
Unbound 最后,创建一个类型Unbound的代理.而它有两个参数,一个是Example的实例,另一个是一个Integer型数据.
下面的代理(Unbound) 将会绑定不带Example实例的方法,实相应的实例参数将会在代理执行过程中进行加载 Unbound notBound
(Unbound)multiplyTestField.CreateDelegate( (Unbound));
outputBlock.Text {0} * Example.Test(42) = {1}\n 10 {0} * Example.Test(56) = {1}\n 56
}
}
代码量不是很大,但又学习又翻译却用了一些时间,希望大家见谅:)
当然如下链接是它的一些在线文档:
[url]http://msdn.microsoft.com/zh-cn/library/system.reflection.emit.dynamicmethod[/url](VS.85).aspx
[url]http://msdn.microsoft.com/zh-cn/library/exczf7b9[/url](en-us,VS.85).aspx
[url]http://technet.microsoft.com/zh-cn/sysinternals/system.reflection.emit.dynamicmethod[/url](VS.85).aspx
好了,今天的内容就先到这里了,呵呵:)
Demo源码包,请 点击这里.
当然如下链接是它的一些在线文档:
[url]http://msdn.microsoft.com/zh-cn/library/system.reflection.emit.dynamicmethod[/url](VS.85).aspx
[url]http://msdn.microsoft.com/zh-cn/library/exczf7b9[/url](en-us,VS.85).aspx
[url]http://technet.microsoft.com/zh-cn/sysinternals/system.reflection.emit.dynamicmethod[/url](VS.85).aspx
好了,今天的内容就先到这里了,呵呵:)
Demo源码包,请 点击这里.
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。