检测缺失方法

本文关键字:方法 检测 | 更新日期: 2023-09-27 18:35:36

>假设我有 2 个由 2 个不同团队维护的 dll:

团队1.dll (v1.0)

public class Foo
{
    int GetValue() { return 3; }
}

团队2.dll (v1.0)

public class Bar
{
    public int IncFooValue(Foo foo) { return foo.GetValue() + 1; }
}

执行 Team1.dll (v1.0) 和 Team2.dll (v1.0) 时,一切正常。但假设 Team1.dll 被更改,方法Foo.GetValue()被删除(v1.1)并放在 Team2 旁边.dll(所有这些都没有重建 Team2.dll)。如果执行,那么你会得到一个 MissingMethodException。

问:如何在不执行 Team1.dll 的情况下检测它们是否不再与 Team2.dll 兼容?

例如,类似这样的内容:

Foreach Class in Team2.dll
    Foreach Method in Class
        Foreach Instruction in Method
            If Instruction not exists in Team1.dll
                Throw "Does not exist"

检测缺失方法

可以通过强制对方法进行 JIT 编译来检测缺少的方法。

为此,您只需要使用反射枚举程序集中的所有方法,然后为每个方法调用RuntimeHelpers.PrepareMethod(method.MethodHandle)

这里棘手的部分是处理泛型。如果方法或类包含泛型,则还需要指定泛型方法将为其抖动的具体类型:

Type[] classGenericArgs = ...;
Type[] methodGenericArgs = ...;
Type[] allGenericArgs = classGenericArgs.Concat(methodGenericArgs).ToArray();
RuntimeHelpers.PrepareMethod(method.MethodHandle, allGenericArgs.Select(p => p.TypeHandle).ToArray());`
         

如果您的泛型参数也有约束,则需要确保您选择的类型满足这些约束,否则,抖动将失败。

满足约束可能很困难,所以我写了一个抖动类来自动化这一点。它强制将应用程序引用的所有库加载到内存中,并通过自动替换泛型方法的适当具体类来运行 jiting(如果可能)。它的用法很简单,只需指定要抖动的程序集:

Jitter.RunJitting(asm => asm.FullName.StartsWith("My.Company.Namespace"));

确保 .NET 应用引用要验证的所有程序集。

您可以在此处找到抖动的源代码。它远非完美,但能够 jit 我们代码库中所有方法的 99.8%,并为我们检测损坏的包依赖项。

检查类型是否包含方法的定义。

if (foo.GetType().GetMethod("GetValue") != null)
{
    return foo.GetValue() + 1;
}

正如其他人所建议的那样,您最好采用另一种策略(更好的版本控制/向后兼容性或处理调用端的异常)。