.NETStandard 1.1 库中的接口在 .NET 4.61 中没有实现

Interface in .NETStandard 1.1 library does not have implementation in .NET 4.61

我正在 .NETStandard 库中定义一个接口,它是 HttpClient 个实例的工厂:

namespace Ofl.Net.Http
{
    public interface IHttpClientFactory
    {
        Task<HttpClient> CreateAsync(HttpMessageHandler handler, 
            bool disposeHandler, CancellationToken cancellationToken);
    }
}

.csproj 文件中的 <FrameworkTarget> 元素设置为 netstandard1.1HttpClient 需要 1.1)。

.NETStandard.Library默认引用1.6.1(虽然没有在.csproj文件中明确指定)。

在同一解决方案中,我从 .NET Standard 项目开始并将 <FrameworkTargets> 元素设置为 netcoreapp1.1;net461

我有一些测试只是为了测试创建接口的实现(我通常不会测试这个,但这将它减少到最小的独立可复制示例)。

为此,我有一个私有实现 IHttpClientFactory:

private class HttpClientFactory : IHttpClientFactory
{
    #region Implementation of IHttpClientFactory

    public Task<HttpClient> CreateAsync(HttpMessageHandler handler, 
        bool disposeHandler, CancellationToken cancellationToken)
    {
        // Return a new client.
        return Task.FromResult(new HttpClient());
    }

    #endregion
}

然后是测试:

[Fact]
public async Task Test_CreateAsync_Interface_Async()
{
    // Cancellation token.
    CancellationToken cancellationToken = CancellationToken.None;

    // The client factory.
    IHttpClientFactory factory = new HttpClientFactory();

    // Not null.
    Assert.NotNull(factory);

    // Create client.
    HttpClient client = await factory.CreateAsync(null, true,
        cancellationToken).ConfigureAwait(false);

    // Not null.
    Assert.NotNull(client);
}

[Fact]
public async Task Test_CreateAsync_Concrete_Async()
{
    // Cancellation token.
    CancellationToken cancellationToken = CancellationToken.None;

    // The client factory.
    var factory = new HttpClientFactory();

    // Not null.
    Assert.NotNull(factory);

    // Create client.
    HttpClient client = await factory.CreateAsync(null, true,
        cancellationToken).ConfigureAwait(false);

    // Not null.
    Assert.NotNull(client);
}

基本上,通过一个具有接口实现类型的变量和一个具有实现类型的变量进行调用class(但这并不重要)。

当 运行 .NETCoreApp 1.1 框架中的测试(通过 Resharper,或 dotnet test)通过所有测试时。但是,当在 .NET Framework 4.6.1 上 运行 时,我得到一个 System.TypeLoadException 说明没有实现:

System.TypeLoadException : Method 'CreateAsync' in type 'HttpClientFactory' from assembly 'Ofl.Net.Http.Abstractions.Tests, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' does not have an implementation.
   at Ofl.Net.Http.Abstractions.Tests.HttpClientFactoryTests.<Test_CreateAsync_Interface_Async>d__1.MoveNext()
   at System.Runtime.CompilerServices.AsyncTaskMethodBuilder.Start[TStateMachine](TStateMachine& stateMachine)
   at Ofl.Net.Http.Abstractions.Tests.HttpClientFactoryTests.Test_CreateAsync_Interface_Async()

为什么在 .NET Framework 4.6.1 上 运行 时测试没有通过?肯定有一个实现。

我认为可能是因为测试项目中没有引用System.Net.Http(在接口定义中不需要,因为引用了.NETStandard 1.6.1,它引用了System.Net.Http)所以我确保添加了它,但在 .NET Framework 4.6.1 下测试仍然失败。

可在此处找到完整设置:

https://github.com/OneFrameLink/Ofl.Net.Http.Abstractions/tree/c2bc5499b86e29c2e0a91282ca7dabcc1acc1176

信息

VS.NET 2017 .NET 命令行界面:1.1.0 .NET 桌面框架:4.61 .NET 核心:1.1

这是因为没有为您的程序集生成具有正确绑定重定向的 .dll.config 文件,并且测试 SDK 没有设置自动执行此操作所需的属性。

您可以通过将此添加到测试的 .csproj 文件来解决此问题:

  <PropertyGroup Condition=" '$(TargetFramework)' == 'net461' ">
    <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
    <GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
  </PropertyGroup>

您会看到这会导致生成一个 bin\Debug\net461\Ofl.Net.Http.Abstractions.Tests.dll.config 文件,其中包含 System.Net.Http 的绑定重定向,并且您的测试应该 运行 正确。

即将推出的 .net 核心/cli 2.0 工具和测试 sdk 将包含一些应该可以解决此问题的更改,但这可能被视为当前工具中的错误。