public static DynamicMethod MulBy2AndAdd1() { var f = DynamicMethod("MultiplyBy2AndAdd1", typeof(int), new[] { typeof(int) }, typeof(DynamicMethodUsingMSIL).Module); OneParameter <int, int> invokeSquareIt = (OneParameter <int, int>) f.CreateDelegate(typeof(OneParameter <int, int>)); }
private static int TestSDivision(int divisions, int invokes) { int i, j; Random rand = new Random(); for (i = 0; i < divisions; i++) { int divisor = rand.Next(Int32.MinValue, Int32.MaxValue); if (divisor == 0 || divisor == -1) { continue; } DynamicMethod SDivision = new DynamicMethod( String.Format("SDivision{0}", i), typeof(int), SDivisionArgs, typeof(T).Module); ILGenerator il = SDivision.GetILGenerator(); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldc_I4, divisor); il.Emit(OpCodes.Div); il.Emit(OpCodes.Ret); OneParameter <int, int> invokeSDivision = (OneParameter <int, int>) SDivision.CreateDelegate(typeof(OneParameter <int, int>)); for (j = 0; j < invokes; j++) { int dividend = rand.Next(Int32.MinValue, Int32.MaxValue); int result, expected; result = invokeSDivision(dividend); expected = dividend / divisor; if (result != expected) { Console.WriteLine("{0} / {1} = {2} != {3})", dividend, divisor, expected, result); return(-1); } } } return(0); }
void StartDynamicMethod() { Type[] methodArgs = { typeof(int) }; DynamicMethod squareIt = new DynamicMethod("SquareIt", typeof(long), methodArgs, typeof(Program).Module); 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); OneParameter <long, int> invokeSquareIt = (OneParameter <long, int>)squareIt.CreateDelegate(typeof(OneParameter <long, int>)); var result = invokeSquareIt(42); Console.WriteLine("42 squared = {0}", result); }
public void EmitDynamicMethod_BindToClass() { // 创建动态方法 // 如果方法的委托要绑定到对象, 第一个参数必须与委托要绑定到的类型匹配 var methodArgs = new[] { GetType(), typeof(int) }; var multiplyHidden = new DynamicMethod( // 名称 string.Empty, // 返回类型 typeof(int), // 参数 methodArgs, // 绑定到的类型 GetType()); // 发出动态方法 ILGenerator iLGenerator = multiplyHidden.GetILGenerator(); // 将类型参数放到堆栈 iLGenerator.Emit(OpCodes.Ldarg_0); var testInfo = GetType().GetField("test", BindingFlags.NonPublic | BindingFlags.Instance); // 寻找当前求值堆栈上引用的对象的一个字段值 iLGenerator.Emit(OpCodes.Ldfld, testInfo); // 将第二个参数加载到堆栈上 iLGenerator.Emit(OpCodes.Ldarg_1); // 将俩个值相乘 iLGenerator.Emit(OpCodes.Mul); // 将结果返回 iLGenerator.Emit(OpCodes.Ret); // 创建委托 OneParameter <int, int> invoker = (OneParameter <int, int>) multiplyHidden.CreateDelegate( typeof(OneParameter <int, int>), Activator.CreateInstance(GetType())); var actual = invoker(3); Assert.Equal(3 * 42, actual); }
public MysqlFastLoader(MySqlDataReader reader) { if (reader.Read()) { Type[] types = { typeof(IDataReader) }; // what we need to do is create a customer reader for this column... method = new DynamicMethod(string.Empty, typeof(void), types); ILGenerator il = method.GetILGenerator(); Label lb = il.DefineLabel(); il.MarkLabel(lb); for (int i = 0; i < reader.FieldCount; i++) { Label dyn = il.DefineLabel(); var typeCode = Type.GetTypeCode(reader.GetFieldType(i)); il.Emit(OpCodes.Ldc_I4, i); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Callvirt, typeof(IDataReader). GetMethod(nameof(IDataReader.IsDBNull), new Type[] { typeof(int) })); il.Emit(OpCodes.Brtrue, dyn); il.Emit(OpCodes.Ldc_I4, i); il.Emit(OpCodes.Ldarg_0); switch (typeCode) { case TypeCode.Boolean: il.Emit(OpCodes.Callvirt, typeof(IDataReader). GetMethod(nameof(IDataReader.GetBoolean), new Type[] { typeof(int) })); il.Emit(OpCodes.Call, typeof(Convert). GetMethod(nameof(Convert.ToString))); break; case TypeCode.Char: il.Emit(OpCodes.Callvirt, typeof(IDataReader). GetMethod(nameof(IDataReader.GetChar), new Type[] { typeof(int) })); il.Emit(OpCodes.Call, typeof(Convert). GetMethod(nameof(Convert.ToString))); break; case TypeCode.SByte: case TypeCode.Byte: il.Emit(OpCodes.Callvirt, typeof(IDataReader). GetMethod(nameof(IDataReader.GetByte), new Type[] { typeof(int) })); il.Emit(OpCodes.Call, typeof(Convert). GetMethod(nameof(Convert.ToString))); break; case TypeCode.Int16: case TypeCode.UInt16: il.Emit(OpCodes.Callvirt, typeof(IDataReader). GetMethod(nameof(IDataReader.GetInt16), new Type[] { typeof(int) })); il.Emit(OpCodes.Call, typeof(Convert). GetMethod(nameof(Convert.ToString))); break; case TypeCode.Int32: case TypeCode.UInt32: il.Emit(OpCodes.Callvirt, typeof(IDataReader). GetMethod(nameof(IDataReader.GetInt32), new Type[] { typeof(int) })); il.Emit(OpCodes.Call, typeof(Convert). GetMethod(nameof(Convert.ToString))); break; case TypeCode.Int64: case TypeCode.UInt64: il.Emit(OpCodes.Callvirt, typeof(IDataReader). GetMethod(nameof(IDataReader.GetInt64), new Type[] { typeof(int) })); il.Emit(OpCodes.Call, typeof(Convert). GetMethod(nameof(Convert.ToString))); break; case TypeCode.Single: il.Emit(OpCodes.Callvirt, typeof(IDataReader). GetMethod(nameof(IDataReader.GetFloat), new Type[] { typeof(int) })); il.Emit(OpCodes.Call, typeof(Convert). GetMethod(nameof(Convert.ToString))); break; case TypeCode.Double: il.Emit(OpCodes.Callvirt, typeof(IDataReader). GetMethod(nameof(IDataReader.GetDouble), new Type[] { typeof(int) })); il.Emit(OpCodes.Call, typeof(Convert). GetMethod(nameof(Convert.ToString))); break; case TypeCode.Decimal: il.Emit(OpCodes.Callvirt, typeof(IDataReader). GetMethod(nameof(IDataReader.GetDecimal), new Type[] { typeof(int) })); il.Emit(OpCodes.Call, typeof(Convert). GetMethod(nameof(Convert.ToString))); break; case TypeCode.DateTime: il.Emit(OpCodes.Callvirt, typeof(IDataReader). GetMethod(nameof(IDataReader.GetDateTime), new Type[] { typeof(int) })); il.Emit(OpCodes.Call, typeof(Convert). GetMethod(nameof(Convert.ToString))); break; case TypeCode.String: il.Emit(OpCodes.Callvirt, typeof(IDataReader). GetMethod(nameof(IDataReader.GetString))); break; default: break; } il.Emit(OpCodes.Call, typeof(Console). GetMethod(nameof(Console.Write), new Type[] { typeof(string) })); il.MarkLabel(dyn); } il.Emit(OpCodes.Call, typeof(Console). GetMethod(nameof(Console.WriteLine), new Type[] { typeof(void) })); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Callvirt, typeof(IDataReader). GetMethod(nameof(IDataReader.Read))); il.Emit(OpCodes.Brtrue, lb); il.Emit(OpCodes.Ret); OneParameter <IDataReader> invokeSquareIt = (OneParameter <IDataReader>) method.CreateDelegate(typeof(OneParameter <IDataReader>)); invokeSquareIt(reader); } //var columnName = reader.GetName(i); //var value = reader[i]; //var dotNetType = reader.GetFieldType(i); //var sqlType = reader.GetDataTypeName(i); //var specificType = reader.GetProviderSpecificFieldType(i); //fieldMetaData.columnName = columnName; //fieldMetaData.value = value; //fieldMetaData.dotNetType = dotNetType; //fieldMetaData.sqlType = sqlType; //fieldMetaData.specificType = specificType; //metaDataList.Add(fieldMetaData); }
//</Snippet12> //</Snippet2> public static void Main() { // Example 1: A simple dynamic method. // // Create an array that specifies the parameter types for the // dynamic method. In this example the only parameter is an // int, so the array has only one element. // //<Snippet3> Type[] methodArgs = { typeof(int) }; //</Snippet3> // Create a DynamicMethod. In this example the method is // named SquareIt. It is not necessary to give dynamic // methods names. They cannot be invoked by name, and two // dynamic methods can have the same name. However, the // name appears in calls stacks and can be useful for // debugging. // // In this example the return type of the dynamic method // is long. The method is associated with the module that // contains the Example class. Any loaded module could be // specified. The dynamic method is like a module-level // static method. // //<Snippet4> DynamicMethod squareIt = new DynamicMethod( "SquareIt", typeof(long), methodArgs, typeof(Example).Module); //</Snippet4> // Emit the method body. In this example ILGenerator is used // to emit the MSIL. DynamicMethod has an associated type // DynamicILInfo that can be used in conjunction with // unmanaged code generators. // // The MSIL loads the argument, which is an int, onto the // stack, converts the int to a long, duplicates the top // item on the stack, and multiplies the top two items on the // stack. This leaves the squared number on the stack, and // all the method has to do is return. // //<Snippet5> 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); //</Snippet5> // Create a delegate that represents the dynamic method. // Creating the delegate completes the method, and any further // attempts to change the method (for example, by adding more // MSIL) are ignored. The following code uses a generic // delegate that can produce delegate types matching any // single-parameter method that has a return type. // //<Snippet6> OneParameter <long, int> invokeSquareIt = (OneParameter <long, int>) squareIt.CreateDelegate(typeof(OneParameter <long, int>)); Console.WriteLine("123456789 squared = {0}", invokeSquareIt(123456789)); //</Snippet6> // Example 2: A dynamic method bound to an instance. // // Create an array that specifies the parameter types for a // dynamic method. If the delegate representing the method // is to be bound to an object, the first parameter must // match the type the delegate is bound to. In the following // code the bound instance is of the Example class. // //<Snippet13> Type[] methodArgs2 = { typeof(Example), typeof(int) }; //</Snippet13> // Create a DynamicMethod. In this example the method has no // name. The return type of the method is int. The method // has access to the protected and private data of the // Example class. // //<Snippet14> DynamicMethod multiplyHidden = new DynamicMethod( "", typeof(int), methodArgs2, typeof(Example)); //</Snippet14> // Emit the method body. In this example ILGenerator is used // to emit the MSIL. DynamicMethod has an associated type // DynamicILInfo that can be used in conjunction with // unmanaged code generators. // // The MSIL loads the first argument, which is an instance of // the Example class, and uses it to load the value of a // private instance field of type int. The second argument is // loaded, and the two numbers are multiplied. If the result // is larger than int, the value is truncated and the most // significant bits are discarded. The method returns, with // the return value on the stack. // //<Snippet15> ILGenerator ilMH = multiplyHidden.GetILGenerator(); ilMH.Emit(OpCodes.Ldarg_0); FieldInfo testInfo = typeof(Example).GetField("test", BindingFlags.NonPublic | BindingFlags.Instance); ilMH.Emit(OpCodes.Ldfld, testInfo); ilMH.Emit(OpCodes.Ldarg_1); ilMH.Emit(OpCodes.Mul); ilMH.Emit(OpCodes.Ret); //</Snippet15> // Create a delegate that represents the dynamic method. // Creating the delegate completes the method, and any further // attempts to change the method — for example, by adding more // MSIL — are ignored. // // The following code binds the method to a new instance // of the Example class whose private test field is set to 42. // That is, each time the delegate is invoked the instance of // Example is passed to the first parameter of the method. // // The delegate OneParameter is used, because the first // parameter of the method receives the instance of Example. // When the delegate is invoked, only the second parameter is // required. // //<Snippet16> OneParameter <int, int> invoke = (OneParameter <int, int>) multiplyHidden.CreateDelegate( typeof(OneParameter <int, int>), new Example(42) ); Console.WriteLine("3 * test = {0}", invoke(3)); //</Snippet16> }
public static void Test() { // Example 1: A simple dynamic method. // // Create an array that specifies the parameter types for the // dynamic method. In this example the only parameter is an // int, so the array has only one element. // Type[] methodArgs = { typeof(int) }; // Create a DynamicMethod. In this example the method is // named SquareIt. It is not necessary to give dynamic // methods names. They cannot be invoked by name, and two // dynamic methods can have the same name. However, the // name appears in calls stacks and can be useful for // debugging. // // In this example the return type of the dynamic method // is long. The method is associated with the module that // contains the Example class. Any loaded module could be // specified. The dynamic method is like a module-level // static method. // DynamicMethod squareIt = new DynamicMethod( "SquareIt", typeof(long), methodArgs, typeof(EmitTest).Module); // Emit the method body. In this example ILGenerator is used // to emit the MSIL. DynamicMethod has an associated type // DynamicILInfo that can be used in conjunction with // unmanaged code generators. // // The MSIL loads the argument, which is an int, onto the // stack, converts the int to a long, duplicates the top // item on the stack, and multiplies the top two items on the // stack. This leaves the squared number on the stack, and // all the method has to do is return. // 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); // Create a delegate that represents the dynamic method. // Creating the delegate completes the method, and any further // attempts to change the method (for example, by adding more // MSIL) are ignored. The following code uses a generic // delegate that can produce delegate types matching any // single-parameter method that has a return type. // OneParameter <long, int> invokeSquareIt = (OneParameter <long, int>) squareIt.CreateDelegate(typeof(OneParameter <long, int>)); Console.WriteLine("2 squared = {0}", invokeSquareIt(2)); }