Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add some helper method to help instantiate generic types and methods #679

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

lovettchris
Copy link

@lovettchris lovettchris commented Jul 13, 2020

Turns out instantiating a generic type or method is non-trivial if you want the newly written assembly to actually work properly. I found these helper methods useful, perhaps others would also. I wasn't sure where the best place to test these helpers would be, do you have any "read/modify/write" assembly tests ? That's the scenario where I found these new helpers to be useful. Actually, we'd want tests that "read/modify/write/execute" to verify the updated assembly loads and runs properly. For example, suppose my assembly contains this generic class:

    class Foo<T>
    {
        public static void Bar<U>(T x, U y)
        {
            Console.WriteLine("Hey this is even more fun: {0}, {1}", x, y);
        }
    }

and i want to read the assembly and add a call to Bar, then write it back out. I can now do this:

var fooType = module.GetType("HelloWorld.Foo`1");
var barMethod = (from m in fooType.Methods where m.Name == "Bar" select m).FirstOrDefault();
var intType = module.ImportReference(typeof(int));

// instantiate Foo<int>.Bar<int>(int x, int y)
var instance = module.ImportGenericMethodInstance(barMethod, intType, intType);
    
// now add call to the method with two constant integer values 10 and 20
// in a test method somewhere:
MethodDefinition testMethod = ... 
var processor = testMethod.Body.GetILProcessor();
var loadint = Instruction.Create(OpCodes.Ldc_I4, 10);
processor.InsertBefore(testMethod.Body.Instructions[0], loadint);
var loadsecondInt = Instruction.Create(OpCodes.Ldc_I4, 20);
processor.InsertAfter(loadint, loadsecondInt);
var callBar = Instruction.Create(OpCodes.Call, instance);
processor.InsertAfter(loadsecondInt, callBar);

// now I can write out the modified assembly and it works.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant