Fody/MethodTimer

FieldAccessException when using Blazor and generic async methods

GeertvanHorrik opened this issue · 4 comments

When trying to trace some methods in Blazor (WASM) in overridden methods, I get a "FieldAccessException".

NetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer ]  Unhandled exception rendering component:  Field `<GetUserAsync>d__2`1:methodTimerMessage' is inaccessible from method `MyApp.UI.Services.MyAppUserManager/<GetUserAsync>d__2`1<Blorc.OpenIdConnect.User`1<Blorc.OpenIdConnect.Profile>>:StopMethodTimerStopwatch ()'
 
 System.FieldAccessException: Field `<GetUserAsync>d__2`1:methodTimerMessage' is inaccessible from method `MyApp.UI.Services.MyAppUserManager/<GetUserAsync>d__2`1<Blorc.OpenIdConnect.User`1<Blorc.OpenIdConnect.Profile>>:StopMethodTimerStopwatch ()'

I am trying to create a repro with unit tests for this.

When investigating the IL, the methodTimerMessage seems to cast the current class where the others are not doing this:

private void StopMethodTimerStopwatch()
{
	if (<>1__state == -2 && methodTimerStopwatch.IsRunning)
	{
		methodTimerStopwatch.Stop();
		methodTimerMessage = null;
		MethodTimeLogger.Log(MethodBase.GetMethodFromHandle((RuntimeMethodHandle)/*OpCode not supported: LdMemberToken*/, typeof(MyAppUserManager).TypeHandle), methodTimerStopwatch.ElapsedMilliseconds, ((<GetUserAsync>d__2<>)(object)this).methodTimerMessage);
	}
}

Also interesting to see that the methodTimerMessage is set to null first.

Differences where the methodTimerStopwatch uses the correct generic class, where methodTimerMessage does not.

ldfld MyApp.Services.MyAppUserManager/'<GetUserAsync>d__2`1'<!TUser>::methodTimerStopwatch
ldfld MyApp.Services.MyAppUserManager/'<GetUserAsync>d__2`1'::methodTimerMessage

I think the issue is the usage of the definition, not the reference, of the field.

Tested the fix, the error is gone now.