为了填充 XNA 框架中锁定的数据类型,我正在使用一个可怕的 hack:我希望在不向垃圾收集器提供数据的情况下调用结构中的一个内部方法。
如果我将上述结构封装在一个对象变量中并使用 MethodInfo.Invoke()
,该调用本身将通过封装参数来为垃圾收集器提供数据:
private object boxedTouchCollection;
void test() {
MethodInfo addTouchLocationMethod = typeof(TouchCollection).GetMethod(
"AddTouchLocation", BindingFlags.Instance | BindingFlags.NonPublic
);
addTouchLocationMethod.Invoke(
this.boxedState, new object[] { /* parameters being boxed */ }
);
}
我不确定是否可以在此处使用 Delegate.CreateDelegate()
- 我可以只将第一个参数转换为一个对象并且它将在盒装结构上工作吗?或者我可以存储未装箱的结构并将第一个参数声明为 ref TouchCollection
吗?
delegate void AddTouchLocationDelegate(
ref TouchCollection collection,
int id,
// ...more parameters...
);
private TouchCollection touchCollection;
void test() {
Delegate.CreateDelegate(
typeof(AddTouchLocationDelegate),
typeof(ref TouchCollection), // doesn't compile
addTouchLocationMethod
);
}
有没有办法让 Delegate.CreateDelegate()
工作?
还是我必须求助于动态 IL 生成?
最佳答案
这是一种方法。
它依赖于this overload Delegate.CreateDelegate
,它创建开放的实例方法委托(delegate)。唯一棘手的一点是,您必须创建适当的委托(delegate)类型才能通过引用传递结构。
我认为不应该对这种技术进行任何装箱——无论是对方法的参数,还是对结构本身。
示例:(为简化示例类型而道歉)
public struct Foo
{
// Internal method to be called. Takes a value-type parameter.
internal void Test(int someParam)
{
Console.WriteLine(someParam);
}
// Custom delegate-type. Takes the Foo instance of interest
// by reference, as well as the argument to be passed on to Test.
public delegate void MyDelegate(ref Foo foo, int someParam);
// Creates type-safe delegate
private static MyDelegate GetTestDelegate()
{
var flags = BindingFlags.Instance | BindingFlags.NonPublic;
var methodInfo = typeof(Foo).GetMethod("Test", flags);
return (MyDelegate) Delegate.CreateDelegate
(typeof(MyDelegate), methodInfo);
}
static void Main()
{
Foo foo = new Foo();
MyDelegate action = GetTestDelegate();
// should dodge boxing
action(ref foo, 42);
}
}
关于c# - 在结构上调用内部方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4227225/