DynamicMethod类允许在运行时生成和执行方法,而不必生成动态程序集和动态类型来包含该方法。动态方法是生成和执行少量代码的最有效方式。
动态方法在逻辑上与模块或类型关联。如果与模块关联,动态方法对于该模块在全局范围内有效。如果有足够的权限,动态方法可以跳过实时 (JIT) 可见性检查,访问在该模块中所声明类型的私有数据。可以将动态方法与任何模块关联,无论该模块是否由您创建。
如果动态方法与类型关联,动态方法可以访问该类型的私有成员。除非动态方法需要访问在同一模块中声明的其他类型的私有数据,否则无需跳过 JIT 可见性检查。可以将动态方法与任何类型关联。
无需对动态方法及其参数进行命名,但是可以指定名称以协助调试。动态方法或其属性不支持自定义属性。
尽管动态方法属于 static 方法,但在 .NET Framework 2.0 版中引入的委托绑定宽松规则允许将动态方法绑定到对象,这使得在使用该委托实例调用动态方法时,可以像调用实例方法那样来调用。下面提供的 CreateDelegate(Type,Object) 方法重载示例对此进行了演示。
class Program { // Declare a delegate type that can be used to execute the completed // dynamic method. private delegate int HelloDelegate(string msg, int ret); static void Main(string[] args) { // Create an array that specifies the types of the parameters // of the dynamic method. This dynamic method has a String // parameter and an Integer parameter. Type[] helloArgs = { typeof(string), typeof(int) }; // Create a dynamic method with the name "Hello", a return type // of Integer, and two parameters whose types are specified by // the array helloArgs. Create the method in the module that // defines the String class. DynamicMethod hello = new DynamicMethod("Hello", typeof(int), helloArgs, typeof(string).Module); // Create an array that specifies the parameter types of the // overload of Console.WriteLine to be used in Hello. Type[] writeStringArgs = { typeof(string) }; // Get the overload of Console.WriteLine that has one // String parameter. MethodInfo writeString = typeof(Console).GetMethod("WriteLine", writeStringArgs); // Get an ILGenerator and emit a body for the dynamic method, // using a stream size larger than the IL that will be // emitted. ILGenerator il = hello.GetILGenerator(256); // Load the first argument, which is a string, onto the stack. il.Emit(OpCodes.Ldarg_0); // Call the overload of Console.WriteLine that prints a string. il.EmitCall(OpCodes.Call, writeString, null); // The Hello method returns the value of the second argument; // to do this, load the onto the stack and return. il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Ret); // Display MethodAttributes for the dynamic method, set when // the dynamic method was created. Console.WriteLine("\r\nMethod Attributes: {0}", hello.Attributes); // Display the calling convention of the dynamic method, set when the // dynamic method was created. Console.WriteLine("\r\nCalling convention: {0}", hello.CallingConvention); // Display the declaring type, which is always null for dynamic // methods. if (hello.DeclaringType == null) { Console.WriteLine("\r\nDeclaringType is always null for dynamic methods."); } else { Console.WriteLine("DeclaringType: {0}", hello.DeclaringType); } // Display the default value for InitLocals. if (hello.InitLocals) { Console.Write("\r\nThis method contains verifiable code."); } else { Console.Write("\r\nThis method contains unverifiable code."); } Console.WriteLine(" (InitLocals = {0})", hello.InitLocals); // Display the module specified when the dynamic method was created. Console.WriteLine("\r\nModule: {0}", hello.Module); // Display the name specified when the dynamic method was created. // Note that the name can be blank. Console.WriteLine("\r\nName: {0}", hello.Name); // For dynamic methods, the reflected type is always null. if (hello.ReflectedType == null) { Console.WriteLine("\r\nReflectedType is null."); } else { Console.WriteLine("\r\nReflectedType: {0}", hello.ReflectedType); } if (hello.ReturnParameter == null) { Console.WriteLine("\r\nMethod has no return parameter."); } else { Console.WriteLine("\r\nReturn parameter: {0}", hello.ReturnParameter); } // If the method has no return type, ReturnType is System.Void. Console.WriteLine("\r\nReturn type: {0}", hello.ReturnType); // ReturnTypeCustomAttributes returns an ICustomeAttributeProvider // that can be used to enumerate the custom attributes of the // return value. At present, there is no way to set such custom // attributes, so the list is empty. if (hello.ReturnType == typeof(void)) { Console.WriteLine("The method has no return type."); } else { ICustomAttributeProvider caProvider = hello.ReturnTypeCustomAttributes; object[] returnAttributes = caProvider.GetCustomAttributes(true); if (returnAttributes.Length == 0) { Console.WriteLine("\r\nThe return type has no custom attributes."); } else { Console.WriteLine("\r\nThe return type has the following custom attributes:"); foreach (object attr in returnAttributes) { Console.WriteLine("\t{0}", attr.ToString()); } } } Console.WriteLine("\r\nToString: {0}", hello.ToString()); // Add parameter information to the dynamic method. (This is not // necessary, but can be useful for debugging.) For each parameter, // identified by position, supply the parameter attributes and a // parameter name. ParameterBuilder parameter1 = hello.DefineParameter( 1, ParameterAttributes.In, "message" ); ParameterBuilder parameter2 = hello.DefineParameter( 2, ParameterAttributes.In, "valueToReturn" ); // Display parameter information. ParameterInfo[] parameters = hello.GetParameters(); Console.WriteLine("\r\nParameters: name, type, ParameterAttributes"); foreach (ParameterInfo p in parameters) { Console.WriteLine("\t{0}, {1}, {2}", p.Name, p.ParameterType, p.Attributes); } // Create a delegate that represents the dynamic method. This // action completes the method, and any further attempts to // change the method will cause an exception. HelloDelegate hi = (HelloDelegate)hello.CreateDelegate(typeof(HelloDelegate)); // Use the delegate to execute the dynamic method. Console.WriteLine("\r\nUse the delegate to execute the dynamic method:"); int retval = hi("\r\nHello, World!", 42); Console.WriteLine("Invoking delegate hi(\"Hello, World!\", 42) returned: " + retval); // Execute it again, with different arguments. retval = hi("\r\nHi, Mom!", 5280); Console.WriteLine("Invoking delegate hi(\"Hi, Mom!\", 5280) returned: " + retval); Console.WriteLine("\r\nUse the Invoke method to execute the dynamic method:"); // Create an array of arguments to use with the Invoke method. object[] invokeArgs = { "\r\nHello, World!", 42 }; // Invoke the dynamic method using the arguments. This is much // slower than using the delegate, because you must create an // array to contain the arguments, and value-type arguments // must be boxed. object objRet = hello.Invoke(null, BindingFlags.ExactBinding, null, invokeArgs, new CultureInfo("en-us")); Console.WriteLine("hello.Invoke returned: " + objRet); } }
本文转自齐师傅博客园博客,原文链接:http://www.cnblogs.com/youring2/archive/2012/06/11/2545694.html,如需转载请自行联系原作者