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

时间:2017-05-13 16:09:51

标签: c# .net .net-core .net-standard

我在.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);
}

基本上,通过具有接口实现类型的变量进行调用,并使用实现类的类型进行调用(尽管无关紧要)。

在.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 CLI:1.1.0 .NET桌面框架:4.61 .NET Core:1.1

1 个答案:

答案 0 :(得分:7)

这是因为没有为您的程序集生成具有正确绑定重定向的.dll.config文件,并且Test 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 core / cli 2.0工具和测试sdk将包含一些应该修复此问题的更改,但这可能被认为是当前工具中的一个错误。