Description
Description
Write generic code to work around that you can't get a static reference to a static method. Since you can cache the reflected instance or use roslyn generator some these limitations have workarounds. However, what we have found is that trying to invoke the static abstract interface method by fetching the method using reflection and then invoking it causes BadImageFormatException to be thrown.
Reproduction Steps
From dotnet/fsharp#14391 (comment)
namespace Foo
{
class C
{
public interface IFoo<T> where T : IFoo<T>
{
static abstract int A();
abstract int B();
}
public struct Foo : IFoo<Foo>
{
public static int A() { return 2; }
public int B() { return 3; }
}
public static int Main(string[] _)
{
var foo = new Foo();
var x = typeof(Foo).GetInterface("IFoo`1").GetMethod("B").Invoke(foo, null);
System.Console.WriteLine(x);
var y = typeof(Foo).GetInterface("IFoo`1").GetMethod("A").Invoke(null, null);
System.Console.WriteLine(y);
/* Throws
System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation.
---> System.BadImageFormatException: Bad IL format.
at Foo.C.IFoo`1.A()
at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
at System.Reflection.MethodInvoker.Invoke(Object obj, IntPtr* args, BindingFlags invokeAttr)
--- End of inner exception stack trace ---
at System.Reflection.MethodInvoker.Invoke(Object obj, IntPtr* args, BindingFlags invokeAttr)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at Foo.C.Main(String[] _)
at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
at System.Reflection.MethodInvoker.Invoke(Object obj, IntPtr* args, BindingFlags invokeAttr)
*/
return 0;
}
}
}
Expected behavior
The expected behaviour would be to match the behaviour of regular instance methods on interfaces (you can invoke them through reflection).
Actual behavior
Instead of being able to call the method we get a BadImageFormatException saying that it is Bad IL format:
System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation.
---> System.BadImageFormatException: Bad IL format.
at Foo.C.IFoo`1.A()
at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
at System.Reflection.MethodInvoker.Invoke(Object obj, IntPtr* args, BindingFlags invokeAttr)
--- End of inner exception stack trace ---
at System.Reflection.MethodInvoker.Invoke(Object obj, IntPtr* args, BindingFlags invokeAttr)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at Foo.C.Main(String[] _)
at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
at System.Reflection.MethodInvoker.Invoke(Object obj, IntPtr* args, BindingFlags invokeAttr)
Regression?
This is a new feature in .net.
Known Workarounds
The workaround is to not use the feature (i.e. use a dummy instance and instance interface methods).
Configuration
Operating system (Windows Appveyor Visual Studio 2022 image, Mac OS X, GitHub Ubuntu latest (2022-11) )
.NET Runtime kind (.NET 7.0.100)
Other information
Originally tracked as issue on F# but then found out that it is not F# specific.