检测缺失方法
本文关键字:方法 检测 | 更新日期: 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;
}
正如其他人所建议的那样,您最好采用另一种策略(更好的版本控制/向后兼容性或处理调用端的异常)。