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

如何在.NET Standard或.NET Core应用运行时重定向方法调用?

替代Microsoft Fakes的.NET调用重定向方案

好问题!确实Microsoft Fakes只支持.NET Framework,在.NET Core/.NET Standard环境下完全没法用,不过我平时做测试和代码调试的时候,积累了几个能实现类似选择性调用重定向功能的方案,分享给你:

1. .NET官方拦截器:System.Runtime.CompilerServices.Interceptors

从.NET 5开始,官方提供了这个拦截器API,支持对方法调用进行重定向,包括静态方法(需要配合[ModuleInitializer]注册拦截器)。比如替换System.DateTime.Now的例子:

using System.Runtime.CompilerServices;
using System.Reflection;

public static class DateTimeInterceptor
{
    [Interceptor]
    public static DateTime InterceptNow()
    {
        // 返回我们指定的固定时间
        return new DateTime(2023, 1, 1);
    }

    [ModuleInitializer]
    public static void RegisterInterceptor()
    {
        var targetMethod = typeof(DateTime).GetProperty(nameof(DateTime.Now))!.GetGetMethod()!;
        var interceptorMethod = typeof(DateTimeInterceptor).GetMethod(nameof(InterceptNow))!;
        InterceptorRegistry.RegisterInterceptor(targetMethod, interceptorMethod);
    }
}

注意这个API需要启用预览功能(在项目文件里设置<EnablePreviewFeatures>true</EnablePreviewFeatures>),目前对系统方法的拦截支持还在逐步完善中,但已经能满足不少场景。

2. Harmony:强大的运行时IL补丁库

这是第三方开源库,几乎能拦截任何.NET方法——不管是静态、非虚、甚至是系统框架里的方法,原理是在运行时修改目标方法的IL代码。比如替换DateTime.Now:

using HarmonyLib;

public class DateTimePatch
{
    public static void ApplyPatch()
    {
        var harmony = new Harmony("com.example.datetimepatch");
        var originalMethod = typeof(DateTime).GetProperty(nameof(DateTime.Now))!.GetGetMethod()!;
        var prefixMethod = typeof(DateTimePatch).GetMethod(nameof(PrefixNow))!;
        
        harmony.Patch(originalMethod, new HarmonyMethod(prefixMethod));
    }

    public static bool PrefixNow(ref DateTime __result)
    {
        __result = new DateTime(2023, 1, 1);
        return false; // 跳过原方法的执行
    }
}

Harmony支持所有.NET Core/.NET Standard版本,是替换系统方法的首选方案之一,很多游戏模组和测试工具都在用它。

3. 依赖注入+包装器模式(适合可控代码)

如果是你自己编写的代码,最稳妥的方式是通过依赖注入封装依赖点,比如把DateTime.Now封装成一个接口:

public interface IDateTimeProvider
{
    DateTime Now { get; }
}

public class DefaultDateTimeProvider : IDateTimeProvider
{
    public DateTime Now => DateTime.Now;
}

在业务代码里依赖IDateTimeProvider,而不是直接调用DateTime.Now,测试的时候就可以轻松替换成模拟实现:

public class MockDateTimeProvider : IDateTimeProvider
{
    public DateTime Now { get; set; } = new DateTime(2023,1,1);
}

这个方法虽然需要提前设计代码结构,但符合SOLID原则,长期维护性更好,适合自己可控的项目。

4. 高级Mock库(如Moq的拦截功能)

最新版本的Moq支持对虚方法、接口方法的拦截,如果你要测试的是自己的类库,而且方法是虚的或者基于接口,用Moq就能轻松实现调用重定向。比如:

var mock = new Mock<IMyService>();
mock.Setup(x => x.DoSomething()).Returns("Mocked Result");
// 调用mock.Object.DoSomething()就会返回预设值

不过要注意,这类Mock库大多只能处理虚方法或接口方法,没法直接拦截静态方法或非虚的系统方法,适合常规的单元测试场景。

总结一下:

  • 需要拦截系统方法/不可修改的代码:选Harmony或.NET官方拦截器
  • 自己的业务代码:优先用依赖注入+包装器模式
  • 常规单元测试(虚方法/接口):用Moq/NSubstitute这类Mock库

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 12:08:30