Dynamically injecting a parameter into a function call in c#
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 vo开发者_如何学Goid 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);
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
.
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();
}
}
Several options:
- Decompile the binary to MSIL, do the changes manually and recompile it.
- User the .NET profiling API to inject code, here is an [article] discussing it.
- 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.
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.
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();
精彩评论