You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用ICSharpCode.Decompiler反编译Moq生成的动态程序集类型

解决Moq动态程序集反编译问题

问题背景

尝试用ICSharpCode.Decompiler反编译Moq生成的动态代理类型时,触发System.NotSupportedException,错误提示动态程序集不支持Location属性。

错误原因

Moq通过System.Reflection.Emit在内存中动态生成代理类型的程序集,这类程序集仅存在于内存中,没有对应的物理磁盘文件,因此Assembly.Location属性调用会抛出异常——该属性仅对已加载到磁盘的程序集有效。

解决方案

先将动态程序集导出到内存流,再基于内存流构建ICSharpCode.Decompiler所需的PEFile和解析器,避免依赖磁盘路径。具体步骤:

  • 检查目标程序集是否为动态程序集
  • 动态程序集通过Assembly.Save方法导出到内存流
  • 使用内存流初始化PEFile,而非磁盘路径
  • 调整程序集解析器,适配内存中的动态程序集

修改后的完整代码

using System.IO;
using System.Reflection;
using System.Reflection.PortableExecutable;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.CSharp;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
using Moq;

public record TestModel;

internal class Program
{
    public static void Main(string[] args)
    {
        foreach (var type in new[] { typeof(TestModel), new Mock<TestModel>().Object.GetType() })
        {
            Assembly currentAssembly = type.Assembly;
            PEFile module;
            UniversalAssemblyResolver assemblyResolver;

            if (currentAssembly.IsDynamic)
            {
                // 动态程序集导出到内存流
                using var ms = new MemoryStream();
                currentAssembly.Save(ms);
                ms.Position = 0;
                module = new PEFile("DynamicAssembly.dll", ms, PEStreamOptions.PrefetchEntireImage);
                assemblyResolver = new UniversalAssemblyResolver(module, false, null);
            }
            else
            {
                // 普通磁盘程序集按原逻辑处理
                module = new PEFile(currentAssembly.Location, PEStreamOptions.PrefetchEntireImage);
                assemblyResolver = new UniversalAssemblyResolver(currentAssembly.Location, false, null);
            }

            var decompilerTypeSystem = new DecompilerTypeSystem(module, assemblyResolver);
            var decompilerSettings = new DecompilerSettings();
            var decompiler = new CSharpDecompiler(module, assemblyResolver, decompilerSettings);
            
            var typeDefinition = decompilerTypeSystem.MainModule.GetTypeDefinition(new FullTypeName(type.FullName));
            var decompiledCode = decompiler.DecompileAsString(typeDefinition.MetadataToken);
            Console.WriteLine("=== 反编译结果 ===");
            Console.WriteLine(decompiledCode);
            Console.WriteLine("\n");
        }
    }
}

项目配置(无需修改)

<Project Sdk="Microsoft.NET.Sdk">

    <PropertyGroup>
        <OutputType>Exe</OutputType>
        <TargetFramework>net6.0</TargetFramework>
        <ImplicitUsings>enable</ImplicitUsings>
        <Nullable>enable</Nullable>
    </PropertyGroup>

    <ItemGroup>
      <PackageReference Include="ICSharpCode.Decompiler" Version="8.1.0.7455" />
      <PackageReference Include="Moq" Version="4.18.4" />
    </ItemGroup>

</Project>

说明

  • 动态程序集导出时,给PEFile指定的DynamicAssembly.dll是虚拟文件名,仅用于标识,不会实际写入磁盘
  • 调整后的代码同时兼容普通磁盘程序集和Moq生成的动态程序集的反编译需求

内容的提问来源于stack exchange,提问作者Node.JS

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 04:27:45