gpt4 book ai didi

c# - 如何解决 C# 中的错误 "ByRef return value not supported in reflection invocation"?

转载 作者:太空狗 更新时间:2023-10-29 21:39:21 24 4
gpt4 key购买 nike

我有一个由第三方提供的 .Net 库。我对他们的一个类进行了反射(reflection),并找到了一个成员方法。签名是……

Byte& FooBar()

所以,我想通过反射调用这个方法,得到了异常“ByRef return value not supported in reflection invocation.”

这是我试过的...

        var strm = new TheirClass();
var t = strm.GetType();
var ms = t.GetMembers(
BindingFlags.Static|BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
foreach (var m in ms)
{
Debug.WriteLine(String.Format("Name: {0}: {1}", m.Name, m.ToString()));
// ...
// Name: FooBar: Byte& FooBar()
// ...
}
var meth = t.GetMethod("FooBar");
object returnValue = meth.Invoke(strm, new object[] { }); //throw exception

我试过像使用 ref 参数调用函数一样提供参数,但这没有任何区别。

我想在 C# 中解决这个异常。

最佳答案

根据评论:这是如何从 CIL 完成的,它可以从 C# 生成。

我希望使用 DynamicMethod,但如果不在运行时创建自定义委托(delegate)类型,我将无法实现此功能,因此我需要改用 AssemblyBuilder

using System;
using System.Reflection;
using System.Reflection.Emit;

public delegate void CallBadFunction(Delegate d, Callback c);
public delegate void Callback(ref int i);

static class Program
{
static int i;
static object BadMethod()
{
return i;
}

static MethodInfo GetBadMethod()
{
return typeof(Program).GetMethod("BadMethod", BindingFlags.Static | BindingFlags.NonPublic);
}

static void Main()
{
var badMethod = GetBadMethod();

var assembly = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("-"), AssemblyBuilderAccess.Run);
var module = assembly.DefineDynamicModule("-");

var badDelegate = module.DefineType("BadDelegateType", TypeAttributes.Public | TypeAttributes.Class | TypeAttributes.Sealed, typeof(MulticastDelegate));
var badDelegateCtor = badDelegate.DefineConstructor(MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName, CallingConventions.Standard, new Type[] { typeof(object), typeof(IntPtr) });
badDelegateCtor.SetImplementationFlags(MethodImplAttributes.Runtime | MethodImplAttributes.Managed);
var badDelegateInvoke = badDelegate.DefineMethod("Invoke", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.NewSlot | MethodAttributes.HideBySig, typeof(int).MakeByRefType(), Type.EmptyTypes);
badDelegateInvoke.SetImplementationFlags(MethodImplAttributes.Runtime | MethodImplAttributes.Managed);
var badDelegateType = badDelegate.CreateType();

var method = module.DefineGlobalMethod("-", MethodAttributes.Public | MethodAttributes.Static, typeof(void), new[] { typeof(Delegate), typeof(Callback) });
var il = method.GetILGenerator();
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Castclass, badDelegate);
il.Emit(OpCodes.Callvirt, badDelegateInvoke);
il.Emit(OpCodes.Callvirt, typeof(Callback).GetMethod("Invoke"));
il.Emit(OpCodes.Ret);
module.CreateGlobalFunctions();

var callBadFunction = (CallBadFunction)Delegate.CreateDelegate(typeof(CallBadFunction), module.GetMethod("-"));
callBadFunction(badMethod.CreateDelegate(badDelegateType), (ref int i) =>
{
i++;
});
}
}

此程序编译后,使用ILDASM反汇编,将BadMethod的定义替换为

.method private hidebysig static int32&
BadMethod() cil managed
{
ldsflda int32 Program::i
ret
}

这将它变成一个返回 int32& 的函数,接下来的代码将设法调用它。 C# 允许 int32& 类型的唯一位置是在函数参数 (ref int) 中,因此为了使结果可用,我使用了一个回调函数,它传递了BadMethod.

关于c# - 如何解决 C# 中的错误 "ByRef return value not supported in reflection invocation"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23349461/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com