Ouch sorry ignore me. CallVirt *does* work with MethodReferences that
contain open genericparameter types. There was an error in my unit-tests.

Sorry

On Wed, Mar 7, 2012 at 9:00 PM, Hendry Luk <[email protected]> wrote:

> That trick works but only up to a certain point. But if your method use
> generic arguments, the  MakeHostInstanceGeneric helper does not seem to
> do the trick.
>
> For instance:
> public class SomeClass<T>
> {
>    public IEnumerable<T> SomeMethod(Func<T> blah)
>    { /* ... */ }
> }
>
> The MakeHostInstanceGeneric only sanitises the DeclaringType of the
> MethodReference, but it does not sanitise method arguments, return-types,
> and so on. And since the generic argument can be wrapped within another
> generic type (e.g. IEnumerable<T> on the method above), the sanitation is
> not exactly trivial.
>
> Using this unsanitised MethodReference (which still contains open
> genericparameter types), it does not seem to produce a valid
> OpCodes.CallVirt instruction.
>
> Any idea how to solve this?
>
> Cheers
>
>
> On Mon, May 23, 2011 at 6:08 AM, Gábor Kozár <[email protected]> wrote:
>
>> This problem has been discussed several times already.
>> Check out this discussion:
>>
>>
>> http://groups.google.com/group/mono-cecil/browse_thread/thread/9826ade54b91e3b2?pli=1
>>
>> In short: when you Resolve() a TypeReference or MethodReference (or any
>> other reference), you loose all generic arguments. You have to then restore
>> those generic arguments by essentially cloning the MethodReference (in your
>> case), except setting its DeclaringType to the original TypeReference
>> (which still contains the generic arguments).
>> The discussion above contains several extension methods that will make
>> this easier for you, but it's important that you know the concept.
>>
>> 2011/5/22 Jean-Paul Mayer <[email protected]>
>>
>>>
>>> I am working on a problem where I want to replace a method on a class
>>> with
>>> a new method.
>>>
>>> I want to transform this:
>>>
>>> public class Foo {
>>>    public int Bar(){
>>>        return 0;
>>>    }
>>> };
>>>
>>> into this:
>>>
>>> public class Foo {
>>>    public int _Call_Bar(string a, string b){
>>>        return 0;
>>>    }
>>>
>>>    public int Bar(string a, string b){
>>>        try {
>>>            //do some preprocessing
>>>            return _Call_Bar(a, b);
>>>        } finally {
>>>            //post processing
>>>        }
>>>    }
>>> }
>>>
>>> I have it mostly working.  However, when Foo has a generic parameter (IE,
>>> public class Foo<T>) then the generated IL looks to be incorrect.
>>>
>>> I end up with a call to
>>>
>>>    L_000d: call instance int32 Demo.Foo`1::_Call_Bar(!T, !T)
>>>
>>> However, when I try to use this new type in an assembly it fails with a
>>> type load exception (PEVerify says the assembly is verified).
>>>
>>> I tried to look at the compiler generated IL as if I had do the
>>> transformation manually, and it ends up with a slightly different call
>>>
>>>
>>>    L_000d: call instance int32 Demo.Foo`1<!T>::_Call_Bar(!T, !T)
>>>
>>>
>>> It looks like the call doesn't know anything about the generic type of
>>> Foo?
>>>
>>> How can I say that the call to _Call_Bar is for type Foo<T>?
>>>
>>> Thanks,
>>>
>>> JP
>>>
>>> --
>>> --
>>> mono-cecil
>>
>>
>>  --
>> --
>> mono-cecil
>
>
>

-- 
--
mono-cecil

Reply via email to