2

I was wondering if it was possible to dynamically inject a function parameter at runtime. For e.g. I have a class with two overloaded methods say

Class C1
{
    public static void Func1(object o)
    {
    }

    public static void Func1()
    {
    }       
}

Class C2
{

    public void Func1()
    {
       C1.Func1();
    }
}

Now, is it possible to dynamically replace the call to Func1() with a call to the overloaded method C1.Func1(object o) passing in either 'this' or the type object as the parameter.

So, in affect when I call C1.Func1(), my code should call C1.Func1(this);

David Basarab
  • 72,212
  • 42
  • 129
  • 156
ilias
  • 2,620
  • 2
  • 27
  • 37
  • I am guessing he wants to intercept/shunt an already compiled piece of code to which he does not have source code access, but knows publics. –  Feb 09 '10 at 18:53
  • 1
    One way would be to decompile the exe to MSIL, make the changes and recompile it. – Amirshk Feb 09 '10 at 18:55

5 Answers5

3

I am assuming that by "dynamic" you mean a post-compile time solution, but not necessarily at runtime. The latter would be more challenging but could be done. For the former it's rather easy if you know some IL. I note that C2.Func1 compiles to something like

.method public hidebysig instance void Func1() cil managed {
    call void SomeNamespace.C1::Func1() 
    ret 
}

which you can easily replace with

.method public hidebysig instance void Func1() cil managed {
    ldarg.0
    call void SomeNamespace.C1::Func1(object)
    ret 
}

This is because argument zero in an instance method is always the this reference for the current instance and we can push it on the stack with the instruction ldarg.0. Moreover, we simply replace the signature of the method that we are invoking from the parameterless method to the method accepting a single object as a parameter.

You can easily decompile to IL using ildasm and recompile using ilasm.

jason
  • 236,483
  • 35
  • 423
  • 525
  • Thanks Jason, that certainly works, however could you explain a bit more about the other option that you suggested, i.e. at runtime, would that mean using the Profiler API as suggested by Am? – ilias Feb 10 '10 at 09:21
2

You can use an extension method:

public static class C1Extensions
{
    public static void Func1(this C1 o)
    {
        // ...
    }
}

public class C1
{
    public void Foo()
    {
       this.Func1();
    }
}
Bryan Watts
  • 44,911
  • 16
  • 83
  • 88
1

Several options:

  1. Decompile the binary to MSIL, do the changes manually and recompile it.
  2. User the .NET profiling API to inject code, here is an [article] discussing it.
  3. Similar issue code-injection-with-c

The code injection would be to intercept the function without the argument, and recall the function with an argument.

Community
  • 1
  • 1
Amirshk
  • 8,170
  • 2
  • 35
  • 64
0

As your method is static there is no way of obtaining the calling object.

Your options are to either make your methods non static and create a C1 object, or, pass the C2 (this) object in as a parameter.

Robin Day
  • 100,552
  • 23
  • 116
  • 167
0

Have you thought about using extension methods to do this?

public static class C1WrappingExtensions {
    public static void Func1(this object instance) {
        C1.Func(instance);
    }
}

// Now you can just call Func1() on any object...
var me = new Whatever();
me.Func1();
Seth Petry-Johnson
  • 11,845
  • 7
  • 49
  • 69