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

如何用C#向目标DLL注入Mock类并实现自动化?

最佳实现方案

针对你需要在MyApp.exe运行前注入Mock版MyDep的需求,最实用的方案分为以下两类,按推荐优先级排序:

1. 运行时代码拦截(推荐使用Harmony框架)

无需修改原DLL,通过拦截MyClass中Dep字段的初始化逻辑,在运行时替换为Mock实例,是最灵活且无侵入的方案。

实现步骤:

  • 新建一个C#控制台项目作为启动器(代替直接启动MyApp.exe)
  • 安装NuGet包 Lib.Harmony
  • 定义Mock类(需实现原DLL中的IMyDep接口):
public class MockMyDep : IMyDep
{
    public void aMethod()
    {
        // 自定义Mock逻辑
        Console.WriteLine("Mocked aMethod executed");
    }
}
  • 在启动器中编写拦截与启动逻辑:
using HarmonyLib;
using System.Diagnostics;
using System.Reflection;

class Program
{
    static void Main(string[] args)
    {
        // 初始化Harmony实例,传入唯一标识
        var harmony = new Harmony("com.your.mock.injector");
        
        // 加载原依赖DLL,获取MyClass类型
        var targetAssembly = Assembly.LoadFrom(@"path\to\your\original.dll");
        var myClassType = targetAssembly.GetType("MyClass");
        
        // 拦截MyClass的无参构造方法,在构造完成后替换Dep字段
        var ctor = myClassType.GetConstructor(Type.EmptyTypes);
        harmony.Patch(ctor, postfix: new HarmonyMethod(typeof(MyClassPatch).GetMethod(nameof(MyClassPatch.Postfix))));
        
        // 启动目标程序MyApp.exe
        Process.Start(@"path\to\MyApp.exe");
    }
}

static class MyClassPatch
{
    // 构造方法执行后的后置补丁
    public static void Postfix(MyClass __instance)
    {
        // 将原Dep字段替换为Mock实例
        __instance.Dep = new MockMyDep();
    }
}

注意:启动器项目需要引用原DLL,确保IMyDep、MyClass等类型可访问;若原DLL未公开这些类型,可通过反射操作字段。

2. 离线修改原DLL的IL代码

通过操作IL指令,直接修改原DLL中MyClass初始化Dep字段的逻辑,替换为Mock类的实例化。适合不希望依赖第三方框架的场景。

实现步骤:

  • 安装NuGet包 Mono.Cecil(用于解析和修改IL)
  • 编写DLL修改与启动代码:
using Mono.Cecil;
using System;
using System.Linq;
using System.Diagnostics;

class DllPatcher
{
    static void Main(string[] args)
    {
        // 加载原DLL
        var assembly = AssemblyDefinition.ReadAssembly(@"path\to\your\original.dll");
        var module = assembly.MainModule;
        
        // 获取原DLL中的MyClass类型
        var myClassType = module.Types.First(t => t.Name == "MyClass");
        // 引入Mock类的类型引用
        var mockType = typeof(MockMyDep);
        var mockTypeRef = module.ImportReference(mockType);
        
        // 找到MyClass的无参构造方法
        var ctor = myClassType.Methods.First(m => m.IsConstructor && !m.IsStatic);
        var ilProcessor = ctor.Body.GetILProcessor();
        
        // 遍历IL指令,替换newobj MyDep为newobj MockMyDep
        foreach (var instr in ctor.Body.Instructions)
        {
            if (instr.OpCode == OpCodes.Newobj && 
                instr.Operand is MethodReference mr && 
                mr.DeclaringType.Name == "MyDep")
            {
                // 引入Mock类的无参构造方法引用
                var mockCtorRef = module.ImportReference(mockType.GetConstructor(Type.EmptyTypes));
                instr.Operand = mockCtorRef;
                break;
            }
        }
        
        // 保存修改后的DLL(可覆盖原文件或保存为新文件)
        assembly.Write(@"path\to\modified.dll");
        
        // 启动MyApp.exe(确保它加载修改后的DLL)
        Process.Start(@"path\to\MyApp.exe");
    }
}

// 必须与原IMyDep接口签名完全一致
public class MockMyDep : IMyDep
{
    public void aMethod()
    {
        // Mock逻辑
    }
}

注意:若原DLL带有强签名,修改后需要用原密钥重新签名;需确保Mock类的命名空间、接口实现与原MyDep完全匹配。

3. 直接替换原DLL类(不推荐)

若原DLL无强签名,可创建与原MyDep同名同命名空间的类,编译成DLL后替换原文件。但该方案灵活性极低,若原DLL中MyDep有其他内部依赖,极易引发运行错误。


内容的提问来源于stack exchange,提问作者Axeltherabbit

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 04:46:31