I've created a custom Fody
weaver using the in-solution approach mentioned here and I'm having some difficulty resolving System.Nullable<T>
types.
Issue:
At runtime, if I call a method with a nullable parameter I get a System.TypeLoadException
stating: 'Could not load type 'System.Nullable`1' from assembly 'MyTargetProject, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.
Purpose
The intent of this weaver is to log the entry and exit of every method (there are some exclusion rules, but not important). I get its class name, method name, parameter name, and parameter value during entry and log execution time at exit. There is no issue when dealing with methods without nullable parameters. When testing with other add-ins such as MethodTimer.Fody
and MethodDecorator.Fody
I found that they didn't quite provide the full functionality that I am looking for.
Investigation
The weaver targets standard2.0 while the projects I weave (8 in total), all target 8.0. What I'm finding is that prior to adding instructions, System.Nullable<T>
and its methods like get_HasValue
or GetValueOrDefault
are resolved by System.Runtime
. However, by adding an IL dump at the end of the method processing (within ModuleWeaver.Execute
) I see the instruction is resolve by the target assembly (i.e., MyTargetProject.dll).
Resolves to System.Runtime
prior to instructions:
WriteDebug($"[DEBUG] hasValueMethod resolved: {hasValueMethodRef.FullName} | DeclaringType: {hasValueMethodRef.DeclaringType.Scope}");
// Output
[DEBUG] hasValueMethod resolved: System.Boolean System.Nullable`1::get_HasValue() | DeclaringType: System.Runtime,
Resolves to MyTargetProject.dll
post-weaving:
instructions.InsertBefore(insertBefore, Instruction.Create(OpCodes.Call, hasValueMethodRef));
// IL Stack
[IL] 0059: call System.Boolean System.Nullable`1<System.Boolean>::get_HasValue() | DeclaringType: MyTargetProject.dll | MetadataToken: [MemberRef:0x0049]
I have also attempted to forcefully resolve System.Nullable<T>
to other assemblies like System.Private.CoreLib.dll
or MyTargetProject.dll
and found similar issues. I've also gone through all weaver project files to ensure there is no use of ModuleDefinition.ImportReference
that could be flattening the reference into the target assembly.
Additionally, when inspecting the IL after successfully building all projects, I see System.Nullable<T>
is resolved as:
IL_0059: call instance bool valuetype [System.Runtime]System.Nullable`1<bool>::get_HasValue()
NOTE: This is the same instruction shown in the IL dump earlier.