Hello,
I'm using version 0.9.6.4 consumed as a NuGet package from nuget.org.
I'm trying to inject a call to a static method, which intercepts values
that would have been returned, and logs/traces/manipulates them in some way
and then returns them. An example of an intercepting method could look like
this:
public static T1 ReturnProxy<T1>(T1 value)
{
// Do something useful with value, like logging it.
var timestamp = DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss.fff",
CultureInfo.InvariantCulture);
StackTrace stackTrace = new StackTrace();
var callingMethod = stackTrace.GetFrame(1).GetMethod();
File.AppendAllLines(@"C:\temp\test_app.txt", new string[] { timestamp + ",
" + callingMethod.Name + ", " + Newtonsoft.Json.JsonConvert.SerializeObject(
value) });
// Now return it just like the calling method would have without this
method intercepting it
return value;
}
And here is what a before/after would look like for injecting the
instructions into the calling method:
// This method is in the assembly being injected into
//BEFORE
public T2 MethodWithAGenericParameter<T2>(int someVariable)
{
T2 obj = (T2)Activator.CreateInstance(typeof(T2));
obj.GetType().GetProperty("MyProperty").SetValue(obj, someVariable);
return obj;
}
//AFTER
public T2 MethodWithAGenericParameter<T2>(int someVariable)
{
T2 obj = (T2)Activator.CreateInstance(typeof(T2));
obj.GetType().GetProperty("MyProperty").SetValue(obj, someVariable);
return Injector.ReturnProxy<T2>(obj);
}
In the case where the return type of the calling method is not generic, the
following code is working correctly to inject the call instructions into
the methods:
public static void InjectReturnProxy(MethodDefinition method)
{
var injectorModuleDef = ModuleDefinition.ReadModule(typeof(Injector).
Module.FullyQualifiedName);
var proxyReturnRefOpen = injectorModuleDef.GetType(typeof(Injector).
FullName).Methods
.First(m => m.FullName == "T TestInjector.Injector::ReturnProxy(T)"
);
ILProcessor processor = method.Body.GetILProcessor();
Instruction proxyReturnInstruction = null;
var genericArg = method.ReturnType.Resolve();
var proxyReturnRefClosed = new GenericInstanceMethod(proxyReturnRefOpen
);
proxyReturnRefClosed.GenericArguments.Add(genericArg);
proxyReturnInstruction = processor.Create(OpCodes.Call, method.Module.
Import(proxyReturnRefClosed));
var returnInstructions = method.Body.Instructions
.Where(i => i.OpCode.Name == "ret").ToArray();
method.Body.OptimizeMacros();
for (var i = 0; i < returnInstructions.Length; i++)
{
var instruction = returnInstructions[i];
processor.InsertBefore(instruction, proxyReturnInstruction);
}
method.Body.SimplifyMacros();
}
However, when the return type of the calling method is generic, like the
MethodWithAGenericParameter example above, I can't seem to get the correct
return type to pass as a generic type argument to the ReturnProxy<T1> static
method. The call to method.ReturnType.Resolve() gives a value of null in
that case, and the type of method.ReturnType is
Mono.Cecil.GenericParameter. I also see problems with a return type of a
generic array (like T[]). I haven't tried to resolve when the return type
of the calling method is a generic type parameter at the class level
instead of the method level, but I suspect I'll have similar issues in that
case. Any thoughts on how to perform the above injection of a method call
passing in as the generic argument the generic parameter of the parent
method? Thanks for any help that could be provided!
--
--
--
mono-cecil
---
You received this message because you are subscribed to the Google Groups
"mono-cecil" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.