DynamicMethod:更接近IL

  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);

        }
    }

 

本文摘自MSDN中对DynamicMethod的描述:http://msdn.microsoft.com/zh-cn/library/system.reflection.emit.dynamicmethod%28v=vs.80%29.aspx

posted @ 2012-06-11 23:27  拓荒者FF  阅读(4688)  评论(3编辑  收藏  举报