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

C# 使用反射唯一标识方法或构造函数,c#,reflection,methodinfo,C#,Reflection,Methodinfo,我需要为任何给定的类唯一地标识一个方法或构造函数,以便在以后的阶段调用它 我曾想过使用ConstructorInfo.GetHashCode和MethodInfo.GetHashCode方法,希望hashcode对于插入MethodBase的每个对象都是唯一的。虽然它们是唯一的,但这也意味着这种方法对我来说是无用的,因为我需要将对象持久化到数据库,以便以后能够运行它,即在重新启动、服务重新启动等之后 到目前为止,我能真正想出唯一标识方法和构造函数的方法是 首先按名称查找匹配方法/构造函数的列表

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

我曾想过使用ConstructorInfo.GetHashCode和MethodInfo.GetHashCode方法,希望hashcode对于插入MethodBase的每个对象都是唯一的。虽然它们是唯一的,但这也意味着这种方法对我来说是无用的,因为我需要将对象持久化到数据库,以便以后能够运行它,即在重新启动、服务重新启动等之后

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

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

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);
    }
}
MethodInfo是可序列化的。这对你的情况可能有用


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

你有没有访问定义你需要调用的方法/代码的代码?如果是这样的话,您可以用一个自定义属性来修饰它们,例如:[MethodNameDefaultCtor],[MethodNameTorIntent]等等。Intent表示这一个最多需要两个Ints,但是,我需要能够从我的项目之外的其他名称空间和类运行代码。请编辑您的问题,以包括您试图解决的实际问题。@SamAxe问题中说明了这个问题,因为我问是否有比我描述的更好的方法,然而,我现在已经明确重申,有没有更好的方法可以使用类中存在的反射唯一地标识方法或构造函数,而不必首先迭代匹配的方法名,然后迭代参数列表以找到第一个匹配项?顺便说一句,MethodInfo是可序列化的。。。返回类型甚至不计入方法签名。但通用参数的数量可能会增加。并且类名仅在同一程序集中是唯一的。因此,也添加程序集签名。它确实没有,但拥有它不会有什么坏处。这只是一个毫无疑问的想法,不想进入死亡。当然,它可以根据实际需要进行修改,例如,可能也不需要完全限定的类型名。声明类型的泛型参数包含在DeclaringType.FullName中。但是应该添加方法本身的泛型参数。谢谢,我已经分别存储了程序集和类名,所以在查找方法时,我已经找到了正确的名称空间/类。我认为这将比序列化整个methodinfo对象更好,因为它仍然是人类可读的,并且可以帮助以后进行调试。谢谢,如果我不必处理持久化对象中的用户可读性,这个方法将是我的首选选项。
foreach (MethodInfo mi in yourType.GetMethods())
{
    if (mi.CreateUniqueName() == stringStoredInDb) { /* do something */ }
}