Reflection.Emit:如何可靠地将MethodBuilder转换为RuntimeMethodInfo?
动态生成类型并调用 TypeBuilder.CreateType 后,我想创建一个指向新类型中的方法的委托。但是,如果我使用像
loadedType = typeBuilder.CreateType();
myDelegate = (MyDelegate)Delegate.CreateDelegate(
typeof(MyDelegate), methodBuilder);
Reusing the methodBuilder as a methodInfo 这样的代码,我会收到异常“MethodInfo 必须是 RuntimeMethodInfo”。现在通常我可以重新获取 MethodInfo
MethodInfo mi = loadedType.GetMethod(methodBuilder.Name);
myDelegate = (MyDelegate)Delegate.CreateDelegate(typeof(MyDelegate), mi);
但我的类可能包含多个同名的重载方法。我如何确保我得到的是正确的?方法是否有一些我可以在loadedType 中查找的持久标识符?
更新:好的,这就是我用来重新获取 MethodInfo 的方法。我只是希望我能确保它在所有情况下都有效。
private static MethodInfo ReacquireMethod(Type type, MethodInfo method)
{
BindingFlags flags = BindingFlags.DeclaredOnly;
flags |= (method.IsPublic ? BindingFlags.Public : BindingFlags.NonPublic);
flags |= (method.IsStatic ? BindingFlags.Static : BindingFlags.Instance);
MethodInfo m = type.GetMethod(method.Name, flags, null,
ParameterTypes(method), null);
Debug.Assert(m != null);
return m;
}
After generating a type dynamically and calling TypeBuilder.CreateType, I want to create a delegate that points to a method in the new type. But if I use code like
loadedType = typeBuilder.CreateType();
myDelegate = (MyDelegate)Delegate.CreateDelegate(
typeof(MyDelegate), methodBuilder);
Reusing the methodBuilder as a methodInfo, I get the exception "MethodInfo must be a RuntimeMethodInfo". Now normally I can re-acquire the MethodInfo with
MethodInfo mi = loadedType.GetMethod(methodBuilder.Name);
myDelegate = (MyDelegate)Delegate.CreateDelegate(typeof(MyDelegate), mi);
But my class may contain several overloaded methods with the same name. How do I make sure I get the right one? Do methods have some persistent identifier I could look up in loadedType?
Update: okay, here's what I'm using to re-acquire the MethodInfo. I just wish I could be sure it works in all cases.
private static MethodInfo ReacquireMethod(Type type, MethodInfo method)
{
BindingFlags flags = BindingFlags.DeclaredOnly;
flags |= (method.IsPublic ? BindingFlags.Public : BindingFlags.NonPublic);
flags |= (method.IsStatic ? BindingFlags.Static : BindingFlags.Instance);
MethodInfo m = type.GetMethod(method.Name, flags, null,
ParameterTypes(method), null);
Debug.Assert(m != null);
return m;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
据我所知,没有持久的共享标识符。
方法的重载通过其参数列表来区分,所以我的猜测是您需要调用
GetParameters
在methodBuilder
上,然后将返回的ParameterInfo[]
数组转换为一个Type[]
数组传递给 适当的GetMethod
重载:As far as I'm aware there's no persistent shared identifier.
Overloads of a method are distinguished by their parameter lists, so my guess is that you'll need to call
GetParameters
onmethodBuilder
and then translate the returnedParameterInfo[]
array into aType[]
array to pass to the the appropriateGetMethod
overload:您需要使用采用类型数组的 GetMethod 重载。方法重载是通过传递给它们的参数来选择绑定的。由于通过反射获取元数据时您实际上并未调用方法,因此您必须提供 Type 对象的有序数组才能获取正确的 MethodInfo 对象:
Type.GetMethod Method (String, Type[])
使用方式如下:
假设 methodBuilder.Name 为“MyMethod”,则绑定以下内容:
请记住,返回类型不是方法签名的一部分,只有方法名称及其参数类型才是。
You need to use the GetMethod overload that takes an array of types. Method overloads are selected for binding by the parameters passed to them. Since you are not actually calling a method when getting their metadata via reflection, you have to provide an ordered array of Type objects to get the right MethodInfo object:
Type.GetMethod Method (String, Type[])
Used like:
Assiming methodBuilder.Name is "MyMethod", that would bind the following:
Remember that the return type is not a part of a method signature, only the method name and its parameter types are.