如何在运行时以类型安全的方式调用泛型方法

时间:2019-04-06 12:08:49

标签: c# generics reflection

我正在尝试在运行时调用通用方法,并具有有效的代码。但是,我想知道是否有更好的方法获取方法信息,因为我应该更改方法名称,否则它将中断。

public int Handle<T>(CreateCodeModel obj) where T : CodeModel
{
     //Create code here...
}

//codeType is selected by user.
public int Handle(CreateCodeModel obj, Type codeType)
{

    MethodInfo method = this.GetType().GetMethod("Handle");
    //MethodInfo method = this.GetType().GetMethods()
            .Where(mi => mi.IsGenericMethod && mi.Name == "Handle").First();

    MethodInfo genericMethod = method.MakeGenericMethod(new Type[] { codeType });
    return (int)genericMethod.Invoke(this, new object[] { obj });

}

我曾经希望有一种更好的方法,也许可以使用动作来获取方法信息,但是我仍然需要提供一种类型,例如

Action<CreateCodeModel> h = (x) => Handle(x);
MethodInfo method = h.Method;

1 个答案:

答案 0 :(得分:0)

您在这里的位置正确。您的委托人签名必须与您要调用的方法匹配,因此在这种情况下将是Func<CreateCodeModel,int>而不是Action<CreateCodeModel>。并且您必须提供与通用约束匹配的通用参数。这可能是任何事情,因为我们只需要调用“ GetGenericMethodDefinition”将其删除,但是我想使用约束中的类。

下面的另一段代码是您只需要获取一次通用方法定义的想法,因为它不会改变,因此我将其存储在一个静态变量中,以便可以重用。

public int Handle<T>(CreateCodeModel obj) where T : CodeModel
{
    //Create code here...
    return 7;
}

// this static variable preserves the generic MethodInfo, so we don't have
// keep discovering it with reflection
private static MethodInfo _methodInfoForHandle;

// The generic MethodInfo only needs to be discovered the first time this runs
private MethodInfo MethodInfoForHandle
{
    get
    {
        return _methodInfoForHandle ?? (_methodInfoForHandle = GetMethodInfoForHandleMethod());
    }
}

private MethodInfo GetMethodInfoForHandleMethod()
{
    Func<CreateCodeModel, int> handleFunc = Handle<CodeModel>;
    return handleFunc.Method.GetGenericMethodDefinition();
}


//codeType is selected by user.
public int Handle(CreateCodeModel obj, Type codeType)
{
    MethodInfo genericMethod = MethodInfoForHandle.MakeGenericMethod(new Type[] { codeType });
    return (int)genericMethod.Invoke(this, new object[] { obj });

}

public class CreateCodeModel { }
public class CodeModel { }
public class JavascriptCodeModel : CodeModel { }