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.

Reply via email to