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

C#如何在不修改原有类定义的前提下部分重写类方法用于测试

方案1:使用动态代理库自动生成透传包装类

装饰器维护成本高的问题可以用运行时代理生成工具解决,.NET生态最常用的是Castle DynamicProxy,它可以在运行时自动生成接口的实现类,所有未显式拦截的方法都会自动转发给传入的真实Model实例,不需要手动写透传代码。
示例代码:

// 1. 安装Castle.Core Nuget包
// 2. 定义拦截器,只处理需要重写的方法
public class ModelMethodInterceptor : IInterceptor
{
    public void Intercept(IInvocation invocation)
    {
        // 只拦截需要修改的GetOther方法
        if (invocation.Method.Name == nameof(IModel.GetOther))
        {
            invocation.ReturnValue = "something for testing";
            return;
        }
        // 其余方法全部转发给真实实例执行
        invocation.Proceed();
    }
}

// 3. 生成代理实例使用
var generator = new ProxyGenerator();
var realModel = new Model();
var testModel = (IModel)generator.CreateInterfaceProxyWithTarget(typeof(IModel), realModel, new ModelMethodInterceptor());
  • 优点:不需要维护包装类,接口变更不需要修改任何透传代码,只需要调整拦截逻辑即可
  • 适用场景:已经为Model提取了公共接口的场景

方案2:Moq/NSubstitute开启CallBase调用原类实现

常用的Mock库都支持类Mock时未配置的方法调用原类实现,只需要显式开启CallBase开关即可:

Moq示例:

// 注意这里直接Mock具体的Model类,不是IModel接口
var mockModel = new Mock<Model>() { CallBase = true };
// 只配置你要重写的方法(注意该方法需要是virtual的才能被重写)
mockModel.Setup(m => m.GetOther()).Returns("something for testing");
// 拿到实例用就行,GetSomething会自动调用原Model的实现
var testModel = mockModel.Object;
  • 优点:无需引入额外依赖,语法简洁,不需要写拦截器
  • 限制:需要被重写的方法是virtual修饰的,如果原类方法没有virtual标记无法重写

方案3:运行时方法重写(适用于非virtual方法的场景)

如果原类的方法没有virtual标记,又不愿意修改生产代码,可以用Harmony库在测试运行时动态重写指定方法的实现,完全不需要修改原类代码,也不需要接口:

// 1. 安装Lib.Harmony Nuget包
// 2. 定义补丁,替换GetOther方法的实现
[HarmonyPatch(typeof(Model), nameof(Model.GetOther))]
public static class ModelGetOtherPatch
{
    static bool Prefix(ref string __result)
    {
        __result = "something for testing";
        // 返回false表示不执行原方法的逻辑
        return false;
    }
}

// 3. 测试启动时应用补丁
var harmony = new Harmony("test.patch");
harmony.PatchAll();
// 之后所有Model实例的GetOther方法都会返回你指定的值,其他方法完全不变
  • 优点:不需要原类有接口,不需要方法是virtual,完全无侵入修改生产代码
  • 限制:仅建议在测试环境使用,生产环境不推荐这种运行时重写的实现方式

方案4:源生成器自动生成通用装饰器

如果接口变更非常频繁,想要编译期检查的能力,可以用C#源生成器写一个通用的装饰器生成工具,输入指定接口,自动生成透传所有方法的partial装饰器类,你只需要在自己的partial类里重写需要修改的方法即可,接口变更时源生成器会自动更新生成的代码,不会出现遗漏方法的编译错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 02:27:01