1

I am trying to weave an assembly by using mono.cecil library. I am injecting a function call at a place in the assembly. The function call has some optional parameters.

But when I inject without loading any value for optional parameters, I get exception on running the modified assembly

I use the following syntax for this:

tempMethod.Body.Instructions.Add( Instruction.create(Opcodes.Call,  methodRef));

where methodRef is an object of type methodReference. methodRef has one optional argument.. but I am not passing any argument over here (using load instruction)

I assume the problem is in the way I am getting methodRef. Is there anything specific, which I need to do for getting methods with optional parameters.

Matthijs
  • 2,483
  • 5
  • 22
  • 33
  • In future, use something like [SharpLab](https://sharplab.io/) to write C# code and see what the generated IL looks like. – Ian Kemp Jan 17 '19 at 06:38

1 Answers1

1

"Optional" parameters are just syntactic sugar: when your code is compiled to IL, the default value of that optional param is explicitly inserted in all places where an explicit value is not provided. Therefore, when emitting your own IL that calls a method with optional parameters, you need to provide the value of those parameters.

This can easily be demonstrated by the below code:

class Program
{
    static void Main(string[] args)
    {
        TestOptional();
        TestOptional(1);
        TestOptional(42);

        Console.ReadKey();
    }

    private static void TestOptional(int? opt = 1)
    {
        Console.WriteLine(opt);
    }
}

If you compile this code and view its disassembly with a decompiler like ILSpy, you'll see that the actual code generated by the compiler looks like this:

TestOptional(1); // note that the "optional" parameter value has been substituted
TestOptional(1);
TestOptional(42);

Aside: the simplest way to "debug" why your IL generation isn't working is to write and compile the expected code, then use a decompiler to view what the compiler has emitted.

Ian Kemp
  • 28,293
  • 19
  • 112
  • 138
  • The reason i am not giving argument is that I am using the [callerfilepath] attribute in the argument ( since i want the caller file path) . so for that the argument shouls not to be passed.. [callerfilepath] automatically fills the default argument.. – Ankit Choudhary Jan 10 '19 at 10:00
  • @AnkitChoudhary Would've been helpful if you'd included that information in your question, but that doesn't change the fact that the string values of `CallerFilePath` and its siblings are filled in at compile-time. Since you're emitting the IL, you're effectively the compiler, so it's your responsibility to provide strings to populate those parameters. I can guess at what you're attempting to achieve with this, but unfortunately it's not going to work. – Ian Kemp Jan 10 '19 at 11:21