Reflection.Emit:如何可靠地将MethodBuilder转换为RuntimeMethodInfo?

发布于 2024-09-05 15:21:29 字数 1154 浏览 4 评论 0原文

动态生成类型并调用 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

时光匆匆的小流年 2024-09-12 15:21:30

据我所知,没有持久的共享标识符。

方法的重载通过其参数列表来区分,所以我的猜测是您需要调用 GetParametersmethodBuilder 上,然后将返回的 ParameterInfo[] 数组转换为一个 Type[] 数组传递给 适当的GetMethod 重载

MethodInfo mi = loadedType.GetMethod(
    methodBuilder.Name,
    methodBuilder.GetParameters().Select(p => p.ParameterType).ToArray());

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 on methodBuilder and then translate the returned ParameterInfo[] array into a Type[] array to pass to the the appropriate GetMethod overload:

MethodInfo mi = loadedType.GetMethod(
    methodBuilder.Name,
    methodBuilder.GetParameters().Select(p => p.ParameterType).ToArray());
黑凤梨 2024-09-12 15:21:30

您需要使用采用类型数组的 GetMethod 重载。方法重载是通过传递给它们的参数来选择绑定的。由于通过反射获取元数据时您实际上并未调用方法,因此您必须提供 Type 对象的有序数组才能获取正确的 MethodInfo 对象:

Type.GetMethod Method (String, Type[])

使用方式如下:

MethodInfo mi = loadedType.GetMethod(
    methodBuilder.Name, 
    new[] 
    { 
        typeof(string), 
        typeof(int) 
    }
);

假设 methodBuilder.Name 为“MyMethod”,则绑定以下内容:

public <returnType> MyMethod(string param1, int param2);

请记住,返回类型不是方法签名的一部分,只有方法名称及其参数类型才是。

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:

MethodInfo mi = loadedType.GetMethod(
    methodBuilder.Name, 
    new[] 
    { 
        typeof(string), 
        typeof(int) 
    }
);

Assiming methodBuilder.Name is "MyMethod", that would bind the following:

public <returnType> MyMethod(string param1, int param2);

Remember that the return type is not a part of a method signature, only the method name and its parameter types are.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文