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

.NET中如何向类构造函数插入IL代码调用?

在.NET中运行时注入静态方法调用到第三方类构造函数的方案

方案一:使用Mono.Cecil修改程序集(预加载修改)

这种方式适合在应用启动时先修改目标程序集的字节码,再加载使用。

步骤:

  • 引用Mono.Cecil NuGet包(Install-Package Mono.Cecil)
  • 加载目标程序集的字节流
  • 定位到目标类及其公开构造函数
  • 在构造函数的IL指令流中插入静态方法调用的IL代码
  • 保存修改后的程序集(可保存到内存或磁盘)
  • 加载修改后的程序集并使用

代码示例:

using Mono.Cecil;
using Mono.Cecil.Cil;
using System;
using System.IO;
using System.Linq;

public static class AssemblyPatcher
{
    public static AssemblyDefinition PatchAssembly(string assemblyPath, Type staticMethodType, string staticMethodName)
    {
        // 加载目标程序集
        var assemblyDef = AssemblyDefinition.ReadAssembly(assemblyPath);
        // 替换为实际目标类名
        var targetType = assemblyDef.MainModule.Types.First(t => t.Name == "TargetClass");
        // 获取无参公开构造函数(带参构造需调整参数匹配逻辑)
        var ctor = targetType.Methods.First(m => m.IsConstructor && m.IsPublic && !m.HasParameters);

        // 导入要调用的静态方法引用
        var module = assemblyDef.MainModule;
        var methodRef = module.ImportReference(staticMethodType.GetMethod(staticMethodName, Type.EmptyTypes));

        // 在构造函数第一条指令前插入静态方法调用
        var ilProcessor = ctor.Body.GetILProcessor();
        var firstInstruction = ctor.Body.Instructions.First();
        ilProcessor.InsertBefore(firstInstruction, ilProcessor.Create(OpCodes.Call, methodRef));

        return assemblyDef;
    }

    // 使用示例
    public static void Main()
    {
        var targetAssemblyPath = "TargetAssembly.dll";
        var patchedAssembly = PatchAssembly(targetAssemblyPath, typeof(MyStaticClass), "MyStaticMethod");

        // 保存到内存并加载
        using var ms = new MemoryStream();
        patchedAssembly.Write(ms);
        ms.Position = 0;
        var loadedAssembly = System.Reflection.Assembly.Load(ms.ToArray());

        // 创建实例时会自动触发注入的静态方法
        var targetInstance = Activator.CreateInstance(loadedAssembly.GetType("TargetClass"));
    }
}

// 要注入的静态方法类
public static class MyStaticClass
{
    public static void MyStaticMethod()
    {
        Console.WriteLine("注入的静态方法被调用了");
    }
}

方案二:使用Harmony进行运行时内存补丁(无需修改程序集文件)

Harmony是专门用于.NET运行时方法补丁的库,适合在程序运行过程中动态修改方法逻辑,无需修改原程序集文件。

步骤:

  • 引用Harmony NuGet包(Install-Package Lib.Harmony)
  • 创建Harmony实例
  • 定义补丁方法,指定在目标构造函数执行前/后调用静态方法
  • 对目标构造函数应用补丁

代码示例:

using HarmonyLib;
using System;

public static class ConstructorPatcher
{
    public static void ApplyPatch()
    {
        var harmony = new Harmony("com.yourcompany.target.patch");
        // 获取目标类的无参公开构造函数(带参构造需匹配参数)
        var targetCtor = typeof(TargetClass).GetConstructor(Type.EmptyTypes);
        // 应用前缀补丁:构造函数执行前调用静态方法
        harmony.Patch(targetCtor, prefix: new HarmonyMethod(typeof(MyStaticClass).GetMethod(nameof(MyStaticClass.MyStaticMethod))));
    }
}

// 要注入的静态方法类
public static class MyStaticClass
{
    public static void MyStaticMethod()
    {
        Console.WriteLine("注入的静态方法被调用了");
    }
}

// 使用示例
public static void Main()
{
    // 确保目标程序集已加载(可通过Assembly.Load加载)
    ConstructorPatcher.ApplyPatch();

    // 创建实例时自动触发注入逻辑
    var targetInstance = new TargetClass();
}

注意事项:

  • 若目标构造函数带参数,补丁方法的参数需与构造函数参数匹配
  • Harmony支持前缀(执行前)、后缀(执行后)、最终(无论异常都执行)三种补丁类型,可按需选择

关键说明

  • 预加载修改方案需确保目标程序集尚未被CLR加载;Harmony方案支持已加载程序集的内存补丁
  • 若目标程序集是强签名的,修改后需用Mono.Cecil.StrongNameKeyPair重新签名才能加载
  • 运行时修改程序集需要足够权限,受限环境(如沙箱)中可能无法执行

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 10:21:02