Reflection.Emit: How to convert MethodBuilder to RuntimeMethodInfo reliably?

你说的曾经没有我的故事 提交于 2019-12-10 19:27:35

问题


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;
}

回答1:


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());



回答2:


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.



来源:https://stackoverflow.com/questions/3031183/reflection-emit-how-to-convert-methodbuilder-to-runtimemethodinfo-reliably

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!