在Mono.Cecil中解析TypeReference到TypeDefinition的过程失败,并出现了程序集解析错误。

3

我正在尝试从.NET类型中获取Mono.Cecil TypeDefinition,但没有成功。

我使用的代码类似于:

var type = typeof(MarkdownMonster.AppConfiguration);

var a = AssemblyDefinition.ReadAssembly(type.Assembly.Location);
var tr = a.MainModule.Import(type);  // this seems to work
var td = tr.Resolve(); // fails

但是它失败了,出现了一个装配体解析错误:

GetConfigurationPropertiesTest [0:29.990] 失败: Mono.Cecil.AssemblyResolutionException : 无法解析程序集: 'MarkdownMonster, Version=1.18.11.0, Culture=neutral, PublicKeyToken=null' Mono.Cecil.AssemblyResolutionException : 无法解析程序集: 'MarkdownMonster, Version=1.18.11.0, Culture=neutral, PublicKeyToken=null' 在 Mono.Cecil.BaseAssemblyResolver.Resolve(AssemblyNameReference name, ReaderParameters parameters) 在 Mono.Cecil.DefaultAssemblyResolver.Resolve(AssemblyNameReference name) 在 Mono.Cecil.MetadataResolver.Resolve(TypeReference type) 在 Mono.Cecil.TypeReference.Resolve() 在 Westwind.TypeImporter.TypeParser.ParseObject(Type type, Boolean dontParseMembers)

显然,程序集在那里,因为 TypeReference 导入似乎起作用并生成有效的 TypeReference。

所涉及到的程序集是一个EXE文件,只是因为好玩而将其重命名为DLL文件,但这没有任何效果。

2个回答

1

这是通常的做法:

        var assembly = @"c:\myassembly.dll";

        var resolver = new DefaultAssemblyResolver();
        
        // add .NET runtime dir for the sake of security
        foreach (var dir in Directory.GetDirectories(RuntimeEnvironment.GetRuntimeDirectory(), "*", SearchOption.AllDirectories))
        {
            resolver.AddSearchDirectory(dir);
        }
        
        // add the assembly's directory
        resolver.AddSearchDirectory(Path.GetDirectoryName(assembly));

        var mod = AssemblyDefinition.ReadAssembly(assembly, new ReaderParameters { AssemblyResolver = resolver }).MainModule;

问候


1
经过一番试验,我找到了一个(丑陋的)解决方案,即创建一个自定义类型解析器,并将硬类型引用强制注入其中。似乎Mono.Cecil能够在找到主程序集后解决瞬态依赖项,但不能解决顶级引用。
为了使其工作,我基本上传递已经解析的程序集引用。在我的情况下,我知道我需要返回的唯一引用将是顶级引用,因此我硬编码了这个。更现实的例子将需要使用AssemblyDefinition.ReadAssembly()从磁盘或流中读取程序集。
以下是创建AssemblyResolver的代码:
    public class MonoAssemblyResolver : IAssemblyResolver
    {
        public AssemblyDefinition AssemblyDefinition;

        public AssemblyDefinition Resolve(AssemblyNameReference name)
        {
            return AssemblyDefinition;
        }

        public AssemblyDefinition Resolve(AssemblyNameReference name, ReaderParameters parameters)
        {

            return AssemblyDefinition;
        }

        public void Dispose()
        {
            AssemblyDefinition = null;
        }
    }

注意欺骗以通过已解决的程序集引用。
现在我可以使用以下代码来解决:
var a = AssemblyDefinition.ReadAssembly(type.Assembly.Location,
            new ReaderParameters() { AssemblyResolver = resolver });

// assign the resolvedr
var resolver = new MonoAssemblyResolver();
resolver.AssemblyDefinition = a;

var tr = a.MainModule.Import(type: type);
var td = tr.Resolve();   // works now

这很繁琐,但可以改成更通用的方式(在我的情况下不需要)。如果Mono.Cecil能够自动解析程序集,那将会更好 - 我不明白为什么它一开始没有找到程序集,因为它位于当前bin文件夹中,而TypeReference可以找到它。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接