删除方法后从 PEVerify 获取 "Type load failed"
Getting "Type load failed" from PEVerify after removing methods
短篇小说
我正在使用以下 Mono.Cecil 代码从接口和实现该接口的 class 中删除除几个方法之外的所有方法。
static void Main(string[] args)
{
var moduleDef = ModuleDefinition.ReadModule("SomeService.dll");
var bigService = moduleDef.Types.Single(t => t.Name == "BigService"); // interface
var bigServiceClient = moduleDef.Types.Single(t => t.Name == "BigServiceClient"); // class implementing above interface
var toSave = new[] {"method1", "method2"};
SaveMethods(bigService, toSave);
SaveMethods(bigServiceClient, toSave);
moduleDef.Write(@"C:\AutobooksCode\MAIN\API\JHA\JHA.SymXchange.V2\bin\Release\JHA.SymXchange.V2_updated.dll");
}
private static void SaveMethods(TypeDefinition typeDef, string[] names)
{
var methodsToSave = typeDef.Methods.Where(m => names.Contains(m.Name, StringComparer.OrdinalIgnoreCase)).ToList();
var ctors = typeDef.Methods.Where(m => m.Name == ".ctor");
methodsToSave.AddRange(ctors);
// remove all methods except the ones I want to save
var pos = 0;
while (true)
{
if (typeDef.Methods.Count == methodsToSave.Count)
break;
if (methodsToSave.Contains(typeDef.Methods[pos]))
pos++;
else
{
typeDef.Methods.RemoveAt(pos);
}
}
}
代码有效,ILDASM 和 JustDecompile 的一切看起来都很好,最重要的是,DLL 可以很好地与客户端一起工作。但是,运行 它通过 PEVerify 为 [token 0x02001C35]
.
生成了 Type load failed.
错误
我使用ILDASM /TOK
查看哪个标记是0x02001C35,它是我正在修改的class (BigServiceClient
)。我只是看不出问题所在。
关于如何进一步调查 PEVerify 错误的任何pointers/ideas/tips?
说来话长
我正在使用旧版 SOAP 界面。我使用 svcutil
来生成代理,但是由于这个接口的遗留特性,这些代理是 巨大的 -- 就像一个 class 中的 1500 多个方法.这在对象创建以及使用 Castle DynamicProxy 进行代理时导致了一些性能问题。
作为快速测试,我从生成的 .cs 代理文件中删除了除两个我需要的方法之外的所有方法(是的,1500 多个中只有两个),重新编译并得到 much 更好的结果。时间从 6-7 秒减少到 20 毫秒以下。
编辑这些文件以手动删除它很乏味,所以我想我会使用 Mono.Cecil 将其自动化。如上所述,一切正常,但我担心 peverify 错误。
我知道你可以用 IL 编织做一些非常复杂和疯狂的事情,但我只需要删除一堆未使用的方法。是的,我可以手动解析生成的源代码并将其从那里删除,但是如果您曾经看过 svcutil
生成的 SOAP 代理,那是我想避免的路径。
发现问题。具有讽刺意味的是,我在编写代码以手动处理源文件并将它们 trim 下来时弄明白了。 :)
在编写源文件处理器时,我注意到 svcutil
生成了一个 implicit interface implementation as well as an explicit interface implementation。我之前的 SaveMethods
代码过于激进并删除了显式实现。我怀疑这是导致 PEVerify 出现 Type load failed
错误的原因。
这是我更新后的 SaveMethods
实现,它生成一个成功完成 PEVerify 的程序集:
private static void SaveMethods(TypeDefinition typeDef, IEnumerable<string> names)
{
var pos = 0;
while (true)
{
if (pos == typeDef.Methods.Count)
break;
var md = typeDef.Methods[pos];
// save ctors, method implementations and explicit interface implementations
if (md.Name == ".ctor" ||
names.Contains(md.Name) ||
(md.Overrides.Count > 0 && names.Contains(md.Overrides[0].Name)))
{
pos++;
}
else
{
typeDef.Methods.RemoveAt(pos);
}
}
}
短篇小说
我正在使用以下 Mono.Cecil 代码从接口和实现该接口的 class 中删除除几个方法之外的所有方法。
static void Main(string[] args)
{
var moduleDef = ModuleDefinition.ReadModule("SomeService.dll");
var bigService = moduleDef.Types.Single(t => t.Name == "BigService"); // interface
var bigServiceClient = moduleDef.Types.Single(t => t.Name == "BigServiceClient"); // class implementing above interface
var toSave = new[] {"method1", "method2"};
SaveMethods(bigService, toSave);
SaveMethods(bigServiceClient, toSave);
moduleDef.Write(@"C:\AutobooksCode\MAIN\API\JHA\JHA.SymXchange.V2\bin\Release\JHA.SymXchange.V2_updated.dll");
}
private static void SaveMethods(TypeDefinition typeDef, string[] names)
{
var methodsToSave = typeDef.Methods.Where(m => names.Contains(m.Name, StringComparer.OrdinalIgnoreCase)).ToList();
var ctors = typeDef.Methods.Where(m => m.Name == ".ctor");
methodsToSave.AddRange(ctors);
// remove all methods except the ones I want to save
var pos = 0;
while (true)
{
if (typeDef.Methods.Count == methodsToSave.Count)
break;
if (methodsToSave.Contains(typeDef.Methods[pos]))
pos++;
else
{
typeDef.Methods.RemoveAt(pos);
}
}
}
代码有效,ILDASM 和 JustDecompile 的一切看起来都很好,最重要的是,DLL 可以很好地与客户端一起工作。但是,运行 它通过 PEVerify 为 [token 0x02001C35]
.
Type load failed.
错误
我使用ILDASM /TOK
查看哪个标记是0x02001C35,它是我正在修改的class (BigServiceClient
)。我只是看不出问题所在。
关于如何进一步调查 PEVerify 错误的任何pointers/ideas/tips?
说来话长
我正在使用旧版 SOAP 界面。我使用 svcutil
来生成代理,但是由于这个接口的遗留特性,这些代理是 巨大的 -- 就像一个 class 中的 1500 多个方法.这在对象创建以及使用 Castle DynamicProxy 进行代理时导致了一些性能问题。
作为快速测试,我从生成的 .cs 代理文件中删除了除两个我需要的方法之外的所有方法(是的,1500 多个中只有两个),重新编译并得到 much 更好的结果。时间从 6-7 秒减少到 20 毫秒以下。
编辑这些文件以手动删除它很乏味,所以我想我会使用 Mono.Cecil 将其自动化。如上所述,一切正常,但我担心 peverify 错误。
我知道你可以用 IL 编织做一些非常复杂和疯狂的事情,但我只需要删除一堆未使用的方法。是的,我可以手动解析生成的源代码并将其从那里删除,但是如果您曾经看过 svcutil
生成的 SOAP 代理,那是我想避免的路径。
发现问题。具有讽刺意味的是,我在编写代码以手动处理源文件并将它们 trim 下来时弄明白了。 :)
在编写源文件处理器时,我注意到 svcutil
生成了一个 implicit interface implementation as well as an explicit interface implementation。我之前的 SaveMethods
代码过于激进并删除了显式实现。我怀疑这是导致 PEVerify 出现 Type load failed
错误的原因。
这是我更新后的 SaveMethods
实现,它生成一个成功完成 PEVerify 的程序集:
private static void SaveMethods(TypeDefinition typeDef, IEnumerable<string> names)
{
var pos = 0;
while (true)
{
if (pos == typeDef.Methods.Count)
break;
var md = typeDef.Methods[pos];
// save ctors, method implementations and explicit interface implementations
if (md.Name == ".ctor" ||
names.Contains(md.Name) ||
(md.Overrides.Count > 0 && names.Contains(md.Overrides[0].Name)))
{
pos++;
}
else
{
typeDef.Methods.RemoveAt(pos);
}
}
}