2010-09-08 67 views
12

项目的存取我添加了一个协接口到我们的项目:构建失败含协变类型

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(); 

所以,一切似乎是正确的,所以我想我的C过度使用是正确的。不幸的是,我们的单元测试项目包含位于同一项目中的某些类型的私有访问器,例如协变接口,这会导致构建失败。

Could not load type 'GenericInheritanceTest.IPresenter_Impl`1' from assembly 'GenericInheritanceTest_Accessor, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' because it declares a covariant or contravariant type parameter and is not an interface or delegate.

这里的问题究竟是什么?在我的实施中是否有失败,如何解决这个问题?不能,我们必须避免使用协变类型的访问器?是否有可能阻止为某些类型创建访问器来解决此问题?

+0

您应该避免一般的私人访问 - 它们会导致测试和生产代码之间的耦合过于紧密。 – Grzenio 2010-09-08 12:37:50

+0

是的,谢谢,但我在这里已经有一个已经存在的项目,它具有120k loc和私人访问器的良好用法,所以它不会只是一个指尖来重写它。 – Enyra 2010-09-08 14:02:55

回答

12

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

根据Bruce Taimana开发的博客条目the private accessor feature已停止,并且可能会在将来版本的Visual Studio中删除。上市可能的替代方案是:

  1. Use the Microsoft.VisualStudio.TestTools.UnitTesting.PrivateObject class to assist in accessing internal and private APIs in your code. This is found in the Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll assembly.

  2. Create a reflection framework that would be able to reflect off your code to access internal or private APIs.

  3. If the code you are trying to access is internal, you may be able to access your APIs using the InternalsVisibleToAttribute so your test code can have access to the internal APIs.

+3

一个迟到的答案,但谢谢:)是的,私人访问者已被弃用,意味着我们删除了我们项目中的所有私人访问者。从您的解决方案列表中,我更喜欢第4点。使用良好的对象结构(IoC)提高可测试性:) – Enyra 2011-09-16 08:46:12

0

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

其实我得到这个错误时,ReSharper的建议,我认为类型参数可协变:

private delegate TResult Action<TResult>(); 

更改为:

private delegate TResult Action<out TResult>(); 

可悲的是,我不得不再次改变它,禁用Resharper在评论中发出警告:

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

因此,一种策略是对ch为:

"<out" 

在项目中,并删除out关键字,只是为了让它编译。 不是非常优雅,但不是非常优雅的微软,因为 这是五年前通过微软连接支持,他们 已选择只是关闭了问题。问题出现在单元测试项目中。它不会帮助将从Visual Studio单元测试框架更改为NUnit测试框架的 。

0

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