获取"类型加载失败"删除方法后{PE 44}}来自PEVerify

时间:2017-01-13 18:11:51

标签: c# mono.cecil ildasm

短篇小说

我使用以下Mono.Cecil代码从接口和实现接口的类中删除除了几个方法之外的所有方法。

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运行它会为Type load failed.生成[token 0x02001C35]错误。

我使用ILDASM /TOK来查看哪个标记是0x02001C35,它是我正在修改的类(BigServiceClient)。我只是看不出问题所在。

有关如何进一步调查PEVerify错误的任何指示/想法/提示?

长篇故事

我正在使用传统的SOAP接口。我使用svcutil生成代理,但由于此接口的遗留特性,这些代理巨大 - 就像单个类中的1500多种方法一样。这导致了对象创建中的一些性能问题以及与Castle DynamicProxy的一些代理。

作为一个快速测试,我从生成的.cs代理文件中删除了我需要的所有方法(是的,1500+中只有2个),重新编译并获得很多更好的结果。时间从6-7秒到20毫秒不等。

编辑这些文件以手动删除它是很乏味的,所以我想我会用Mono.Cecil自动删除它。如上所述,一切都运行正常,但我关注的是peverify错误。

我知道你可以用IL编织做一些非常复杂和疯狂的东西,但我只需要删除一堆未使用的方法。是的,我可以手动解析生成的源代码并将其删除,但如果您曾见过svcutil生成的SOAP代理,那么我想避免使用它。< / p>

1 个答案:

答案 0 :(得分:0)

发现了这个问题。具有讽刺意味的是,我在编写代码时手动处理源文件并将其修剪下来。 :)

在编写源文件处理器时,我注意到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);
        }
    }
}