Search code examples
c#reflection.emitdynamicmethoddynamic-method

How to call a dynamic method to return square of number?


I want to create a simple dynamic method that returns square of a integer number(i.e - If number is 5, it should return 25).
I have written the code below:-

class Square
{
    public int CalculateSquare(int value)
    { return value * value; }
}
public class DynamicMethodExample
{
    private delegate int SquareDelegate(int value);
    internal void CreateDynamicMethod()
    {

        MethodInfo getSquare = typeof(Square).GetMethod("CalculateSquare");

        DynamicMethod calculateSquare = new DynamicMethod("CalculateSquare",
            typeof(int),new Type[]{typeof(int)});


        ILGenerator il = calculateSquare.GetILGenerator();
        // Load the first argument, which is a integer, onto the stack.
        il.Emit(OpCodes.Ldarg_0);
        il.Emit(OpCodes.Mul);
        // Call the overload of CalculateSquare that returns the square of number
        il.EmitCall(OpCodes.Call, getSquare,null);            
        il.Emit(OpCodes.Ret);



        SquareDelegate hi =
        (SquareDelegate)calculateSquare.CreateDelegate(typeof(SquareDelegate));

        Console.WriteLine("\r\nUse the delegate to execute the dynamic method:");
        int retval = hi(42);
        Console.WriteLine("Calculate square returned " + retval);
    }
}

Why am I getting "InvalidProgramException" at

int retval = hi(42);

How can I get this thing to work?


Solution

  • You have a couple of issues. First, the Square class must be public, and its CalculateSquare method must be static. Second, you don't want to emit a Mul if you are calling the method to multiply. Here's your code with those fixes:

    public class Square
    {
        public static int CalculateSquare( int value )
        { return value * value; }
    }
    
    public class DynamicMethodExample
    {
        private delegate int SquareDelegate( int value );
    
        internal void CreateDynamicMethod()
        {
    
            MethodInfo getSquare = typeof( Square ).GetMethod( "CalculateSquare" );
    
            DynamicMethod calculateSquare = new DynamicMethod( "CalculateSquare",
                typeof( int ), new Type[] { typeof( int ) } );
    
    
            ILGenerator il = calculateSquare.GetILGenerator();
            // Load the first argument, which is a integer, onto the stack.
            il.Emit( OpCodes.Ldarg_0 );
            // Call the overload of CalculateSquare that returns the square of number
            il.Emit( OpCodes.Call, getSquare );
            il.Emit( OpCodes.Ret );
    
    
    
            SquareDelegate hi =
            ( SquareDelegate )calculateSquare.CreateDelegate( typeof( SquareDelegate ) );
    
            Console.WriteLine( "\r\nUse the delegate to execute the dynamic method:" );
            int retval = hi( 42 );
            Console.WriteLine( "Calculate square returned " + retval );
    
        }
    }