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

如何解决WPF单元测试中无法加载DispatcherTimer类型的异常

解决.NET 7测试项目加载WindowsBase中DispatcherTimer类型失败的问题

原因分析

你的测试项目目标框架是.NET 7(属于.NET Core生态),而被测试的WPF项目基于.NET Framework 4.7.2,两者的WindowsBase.dll分属不同技术生态,版本与底层实现存在差异,导致运行时无法匹配到正确的类型。

解决办法

方案一:将测试项目切换为.NET Framework 4.7.2

这是最直接的解决方案,确保测试与被测试项目框架完全一致:

  • 右键测试项目 → 属性 → 应用 → 目标框架,选择.NET Framework 4.7.2
  • 重新引用WPF项目,编译调试即可彻底避免程序集版本冲突

方案二:在.NET 7测试项目中引入WPF依赖并配置绑定重定向

如果必须保留.NET 7测试项目,需让项目正确识别WPF相关程序集:

  1. 修改测试项目的.csproj文件,添加WPF支持:
<PropertyGroup>
  <TargetFramework>net7.0-windows</TargetFramework>
  <UseWPF>true</UseWPF>
</PropertyGroup>
  1. 新建或修改app.config文件,添加程序集绑定重定向,引导运行时加载正确版本的WindowsBase:
<configuration>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="WindowsBase" publicKeyToken="31bf3856ad364e35" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="7.0.0.0" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
</configuration>

方案三:抽象定时器依赖,实现无耦合测试

通过接口解耦Battery类与DispatcherTimer的直接依赖,从根源消除跨框架程序集问题:

  1. 定义定时器接口:
public interface ITimer
{
    event EventHandler Tick;
    TimeSpan Interval { get; set; }
    void Start();
    void Stop();
}
  1. 在WPF项目中实现基于DispatcherTimer的适配器:
public class DispatcherTimerAdapter : ITimer
{
    private readonly DispatcherTimer _timer;

    public event EventHandler Tick;

    public TimeSpan Interval
    {
        get => _timer.Interval;
        set => _timer.Interval = value;
    }

    public DispatcherTimerAdapter()
    {
        _timer = new DispatcherTimer();
        _timer.Tick += (s, e) => Tick?.Invoke(s, e);
    }

    public void Start() => _timer.Start();
    public void Stop() => _timer.Stop();
}
  1. 修改Battery类,通过构造函数注入ITimer:
public class Battery
{
    private readonly ITimer _timer;

    public Battery(ITimer timer)
    {
        _timer = timer;
        _timer.Interval = TimeSpan.FromSeconds(1);
        _timer.Tick += OnTimerTick;
    }

    private void OnTimerTick(object sender, EventArgs e)
    {
        // 原有定时器逻辑
    }
}
  1. 测试项目中使用模拟定时器,手动控制事件触发:
public class MockTimer : ITimer
{
    public event EventHandler Tick;
    public TimeSpan Interval { get; set; }

    public void Start() { }
    public void Stop() { }

    // 测试时手动触发Tick事件
    public void RaiseTick() => Tick?.Invoke(this, EventArgs.Empty);
}

这种方式不仅解决了跨框架问题,还让测试逻辑更灵活,无需依赖WPF运行环境。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 19:05:56