14

我在我们的项目中添加了一个协变接口:

interface IView
{
}

interface IPresenter<out TView> where TView : IView
{
    TView View { get; }
}

我创建了一些类,实现了这些接口:

class TestView : IView
{
}

class TestPresenter : IPresenter<TestView>
{
  public TestView View
  {
    get { return something; }
  }

  private void DoSomething()
  {
  }
}

我可以毫无问题地使用它:

IPresenter<IView> presenter = new TestPresenter();

所以一切似乎都是正确的,所以我假设我的协方差使用是正确的。不幸的是,我们的单元测试项目包含来自同一项目中某些类型的私有访问器,例如协变接口,这会导致构建失败。

无法从程序集“GenericInheritanceTest_Accessor,Version=0.0.0.0,Culture=neutral,PublicKeyToken=null”加载类型“GenericInheritanceTest.IPresenter_Impl`1”,因为它声明了协变或逆变类型参数,而不是接口或委托。

这里到底有什么问题?我的实施是否有失败,分别。如何解决这个问题?不可能,一旦我们使用协变类型,我们就必须避免访问器???是否可以阻止为某些类型创建访问器来解决此问题?

4

3 回答 3

14

这是 Visual Studio 2010 中的错误。已向Microsoft Connect报告,但已关闭,显然不会修复。

根据 Bruce Taimana 的一篇博客文章,私有访问器功能的开发已经停止,并且可能会在 Visual Studio 的未来版本中被删除。列出的可能替代方案是:

  1. 使用Microsoft.VisualStudio.TestTools.UnitTesting.PrivateObject该类来帮助访问代码中的内部和私有 API。这可以在Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll程序集中找到。

  2. 创建一个反射框架,该框架能够反射您的代码以访问内部或私有 API。

  3. 如果您尝试访问的代码是内部代码,您可以使用 访问您的 API,InternalsVisibleToAttribute以便您的测试代码可以访问内部 API。

于 2011-09-15T11:21:03.867 回答
1

我一直在努力解决这个错误并且也遇到了一个错误:“BuildShadowTask”意外失败。当我在这里尝试解决该错误时,摆脱该错误的唯一方法是从泛型中删除 out 关键字,即协变接口。

实际上,当 Resharper 向我建议类型参数可能是协变的时,我得到了这个错误:

private delegate TResult Action<TResult>(); 

变成:

private delegate TResult Action<out TResult>();

可悲的是,我不得不再次将其改回并在评论中禁用 Resharper 警告:

// ReSharper disable once TypeParameterCanBeVariant 
private delegate TResult Action<TResult>();

因此,一种策略可以是搜索:

"<out"

在一个项目中并删除 out 关键字,只是为了让它编译。不是很优雅,但微软也不是很优雅,因为这是五年前通过 Microsoft Connect 报告的,他们选择只是关闭问题。问题出在单元测试项目中。从 Visual Studio 单元测试框架更改为 NUnit 测试框架并没有帮助。

于 2015-05-24T19:31:22.580 回答
0

如果您使用 Unity Interception,并且您的参数标记为 out,则 Unity Interception 会导致此错误。这样做的原因是 Interception 必须能够读取参数列表。所以与上面的情况类似,如果 Resharper 警告参数可以是协变的,则需要忽略此警告。

于 2016-06-27T14:54:47.043 回答