繁体   English   中英

使用反射唯一标识方法或构造函数

[英]Uniquely identifying a method or constructor using reflection

我需要为任何给定的类唯一地标识一个方法或构造函数,以便以后可以调用它。

我曾考虑过使用ConstructorInfo.GetHashCode()MethodInfo.GetHashCode()方法,希望哈希码对于继承MethodBase每个对象都是唯一的。 尽管它们是唯一的,但它们在程序的每次运行时也会改变,这意味着该方法对我来说毫无用处,因为我需要将对象持久保存到数据库中,以便以后可以运行它(即,在重启,服务重启等之后)。

到目前为止,我真正想出的唯一标识方法和构造函数的唯一方法是

  1. 首先按名称查找匹配方法/构造函数的列表
  2. 迭代匹配的方法/构造函数,以查看哪个参数列表与我想要的参数列表匹配。

有没有更好的方法可以使用类中存在的反射来唯一地标识方法或构造函数,而不必首先迭代匹配的方法名称,然后迭代参数列表以查找第一个匹配项?

methodParams = null;
constructorInfo = null;

var methods = instanceType.GetMethods().Where(m => m.Name == constructorName);//this is required to handle methods that are overloaded
foreach (var method in methods)
{
    var internalParams = method.GetParameters();
    if (internalParams.Count() == requiredParams.Count())
    {
        var methodParamDict = internalParams.ToDictionary(x => x.Name, x => String.Empty);
        foreach (var requiredParamKey in requiredParams.Keys)
        {
            if (methodParamDict.ContainsKey(requiredParamKey))
            {
                methodParamDict[requiredParamKey] = requiredParams[requiredParamKey];
            }
        }
        if (methodParamDict.All(x => x.Value != String.Empty))
        {
            //set the methodParams to internalParams (i.e. we have found the correct overloaded method)
            methodParams = internalParams;
            constructorInfo = method as ConstructorInfo;
        }
    }
}

包括Stefan的建议,您可以定义一个扩展方法类,如下所示:

public static class CustomReflectionHelpers
{
    public static String CreateUniqueName(this MethodInfo mi)
    {
        String signatureString = String.Join(",", mi.GetParameters().Select(p => p.ParameterType.Name).ToArray());
        String returnTypeName = mi.ReturnType.Name;

        if (mi.IsGenericMethod)
        {
            String typeParamsString = String.Join(",", mi.GetGenericArguments().Select(g => g.AssemblyQualifiedName).ToArray());


            // returns a string like this: "Assembly.YourSolution.YourProject.YourClass:YourMethod(Param1TypeName,...,ParamNTypeName):ReturnTypeName
            return String.Format("{0}:{1}<{2}>({3}):{4}", mi.DeclaringType.AssemblyQualifiedName, mi.Name, typeParamsString, signatureString, returnTypeName);
        }

        return String.Format("{0}:{1}({2}):{3}", mi.DeclaringType.AssemblyQualifiedName, mi.Name, signatureString, returnTypeName);
    }
}

然后,您可以像这样简化比较:

foreach (MethodInfo mi in yourType.GetMethods())
{
    if (mi.CreateUniqueName() == stringStoredInDb) { /* do something */ }
}

MethodInfo是可序列化的。 这可能对您有用。

请参阅此示例

这样做的一个缺点是,当您将二进制文件更新到较新的版本并且仍然想找到该方法时,就会遇到问题。 (对于这种情况,您也应该考虑不使用方法名称。)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM