【问题标题】:Overloaded method not found未找到重载方法
【发布时间】:2018-07-24 19:12:43
【问题描述】:

设置如下:

  • .NET Standard 2.0 库
  • 一个针对它的 NUnit 测试项目,针对 .NETFramework 4.6.1

最新的 VS 2017,最新的 NUnit。

我周末在家一直在做这个项目,将我的工作上传到 git,今天开始下班(我之前已经在这两个地方工作过)。直到现在我才发现项目出了点问题(我不太记得一开始出了什么问题,但问题似乎和我现在一样,稍后描述)。

在摆弄到无法修复的状态后,我完全删除了它并重新克隆了 git repo。

项目编译良好​​strong>,但在运行时测试抛出“找不到方法”异常。稍微摸索一下,发现问题仅在以下方法的一个重载上表现出来:

    public static YNABClient GetInstance(HttpMessageHandler _handler)
    {
        if (instance is null)
        {
            instance = new YNABClient(_handler);
        }

        return instance;
    }

    public static YNABClient GetInstance() => GetInstance(new HttpClientHandler());

不带参数的可以,带参数的不行。删除和添加库作为对测试的引用,删除和添加测试和库项目。我在互联网上找到的针对类似情况的其他解决方案都与 ASP.NET MVC 相关,这不是我的情况,尽管this 问题确实让我检查了重载并发现其中一个确实有效。

虽然我还没有像在工作中那样尝试删除并重新安装该项目,但在家里一切仍然正常。这导致了 2 个可能的问题来源:环境,尽管我没有设法找到有意义的差异,或者 git,尽管我对 VS (this one) 使用“库存” git ignore,所以应该没有问题那里。我的项目的基本设置在周末没有改变并且之前工作过,所以最近的摆弄有些东西坏了。

另外,如果我将控制台应用程序(.Net Framework 4.6.1)添加到解决方案并尝试从中调用有问题的方法,它实际上可以正常工作。

如果有帮助,我的项目 github 是 here

有人要求我在 cmets 中调用示例。基本上,我有 2 个具有不同设置的测试夹具类 - 一个用于真正的 API 调用,以便于调试实际使用,另一个用于伪造它,根据良好的测试实践。 作品:

    [OneTimeSetUp]
    public void Setup()
    {
        ynabClient = YNABClient.GetInstance();
        ynabClient.RefreshAccessToken(ApiKeys.AccessToken);
    }

抛出异常:

    [OneTimeSetUp]
    public void Setup()
    {
        handler = new StubHandler();
        ynabClient = YNABClient.GetInstance(handler);
    }

一些研究表明我的问题很可能与 System.Net.Http 与 .NET Framework 和 .NET Standard 的版本差异有关,如果您在谷歌上搜索,这是一个相当普遍的问题。然而,我挖出的例子都没有表现出我的特殊症状,我还不知道该怎么做。以及为什么在我的家用电脑上一切正常。

【问题讨论】:

  • 由于问题只发生在运行时,您需要发布您使用反射(或使用dynamic)调用GetInstance 方法的位置。由于某种原因,运行时绑定器无法将参数匹配到静态方法。
  • 正如我所说,我从 NUnit 测试项目中调用它。是公开的,不需要反思。虽然我不知道 NUnit 在内部是如何工作的,但那里的一切都很简单。我将添加示例
  • 当我运行你的测试时,模拟测试都通过了,但真正的测试都失败了:“YNAB 没有授权我们。访问令牌可以吗?”听起来模拟测试对您来说失败了,我无法用您的代码重现。请尝试将其减少为minimal reproducible example
  • 您的尝试确实验证了问题出在环境上。所有测试都按照它们应该为您执行的操作 - 模拟通过,因为它们没有外部依赖项,而真实的则返回未经授权的异常,因为您没有提供访问密钥。
  • 是因为你的框架吗?您的 YNABConnector 是 .NET Standard 2.0,但您的 UnitTest 是 4.6.1。

标签: c# visual-studio-2017 methodnotfound


【解决方案1】:

您遇到的问题是您的GetInstance 方法接受HttpMessageHandler 作为参数,并且在您的test 中您传递的是HttpClientHandler 对象。因此,您声明了一个参数,但在调用方法时提供了不同的对象。

【讨论】:

    【解决方案2】:

    我在我的环境中遇到了这个错误:

    严重性代码描述项目文件行抑制状态 错误 CS0433 类型 'HttpMessageHandler' 存在于两者中 'System.Net.Http,版本=4.2.0.0,文化=中性, PublicKeyToken=b03f5f7f11d50a3a' 和 'System.Net.Http, 版本=4.0.0.0,文化=中性,PublicKeyToken=b03f5f7f11d50a3a'

    您的 YNABConnector 是 .NET Standard 2,但单元测试是 4.6.1,它们对同一程序集使用不同的签名。

    这里是官方文档来测试: https://github.com/nunit/docs/wiki/.NET-Core-and-.NET-Standard

    1. 创建了一个 .NET Core 库(注意:不能通过上面的链接成为 .NET Standard 库),
    2. 在那里复制你的测试代码,
    3. 按照官方文档添加引用,

    你的代码可以正常工作,没有错误。

    但是在你的基础代码中,我还是更喜欢这个代码:

    public class YNABClient
    {
        private static YNABClient instance;
    
        private HttpClient client;
    
        private HttpMessageHandler handler;
    
        private YNABClient(HttpMessageHandler _handler = null)
        {
            handler = _handler ?? new HttpClientHandler();
            client = new HttpClient(_handler);
        }
    
        public static YNABClient GetInstance(HttpMessageHandler _handler = null)
        {
            return instance ?? (instance = new YNABClient(_handler));
        }
    
        ......
    }
    

    【讨论】:

    • HttpMessageHandler 是一个抽象类。 HttpClientHandler 是它的默认值。在测试期间交换依赖项需要使用另一个处理程序实例化客户端 - 我们不想在测试解析器时实际将任何内容发布到真实服务器。虽然这是我将来可能想做的事情的次优实现,但现在这符合预期。再次阅读问题 - 方法的无参数版本实际上有效。
    • 好吧,现在这真的是离题了,但是看看 StubHandler 和它在测试库中的使用来理解为什么参数被声明为它的原样。摆脱重载对我来说太暴力了。他们没有理由不工作,你知道,这只是一个被压扁的错误。 Daisy Shipton 在问题的 cmets 中证明了这一点,因为一切都对他有用
    • 是因为你的框架吗?您的 YNABConnector 是 .NET Standard 2.0,但您的 UnitTest 是 4.6.1?
    【解决方案3】:

    所以,正如 DongDong 建议的那样,问题确实出在 .NET Framework 和 .NET Standard 之间的接口上。问题不在于它们不兼容,或者测试项目需要一些额外的依赖项,而是它们附带不同版本的 System.Net.Http。

    没有显示任何可见错误,阻碍了诊断。但是,更改参数类型确实表明,问题仅在于该命名空间中的类。

    诊断问题的另一个问题是该项目在某些机器上运行良好(我的家用 PC 和 Daisy Shipton 从 cmets 到问题)。

    然而,在确定问题的根源后,我能够首先在谷歌上搜索该库存在哪些问题,最终在.NET github 上发现了一大堆不兼容问题。

    我尝试了在这些情况下使用的解决方案,并向库的具体版本添加了“绑定重定向”,之后它就可以正常工作了。我将重定向添加到我的测试项目的app.config。作为参考,它看起来像这样:

    <dependentAssembly>
        <assemblyIdentity name="System.Net.Http" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-4.2.0.0" newVersion="4.2.0.0" />
    </dependentAssembly>
    

    我仍然不明白为什么该项目在某些机器上运行良好。

    【讨论】:

    • .NET Standard 2 比 4.6.1 更新,它应该具有在旧版本中无法使用的新功能。但我应该得到你的支持!
    • 你做到了 :) 你也得到了某人的反对票,所以这是 0。另一个答案更值得它,但是......另外,。 Net Standard 应该与每个文档 docs.microsoft.com/en-us/dotnet/standard/net-standard 的 4.6.1 完全兼容,因此新旧与它无关:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-19
    • 2021-12-17
    • 1970-01-01
    • 2010-11-16
    • 1970-01-01
    相关资源
    最近更新 更多