2010-04-20 219 views
10

这是一个在我看来应该通过但不是的测试。打开通用接口类型的开放实现不等于接口类型?

[TestMethod] 
public void can_get_open_generic_interface_off_of_implementor() 
{ 
    typeof(OpenGenericWithOpenService<>).GetInterfaces().First() 
     .ShouldEqual(typeof(IGenericService<>)); 
} 
public interface IGenericService<T> { } 
public class OpenGenericWithOpenService<T> : IGenericService<T> { } 
  1. 为什么会出现这种不通过?
  2. 鉴于Type t = typeof(OpenGenericWithOpenService<>)如何获得typeof(IGenericService <>)?

我一般很好奇,但是如果你想知道我在做什么,我正在编写一个Structuremap约定,将实现的所有接口转发给实现(作为单例)。

+0

破解问题。调查:) – 2010-04-20 20:25:27

+0

如果你真的想让测试通过,你可以比较GUID。 – 2010-04-20 20:33:56

回答

7

OpenGenericWithOpenService<T>没有实现只是一个任意IGenericService<> - 它实现IGenericService<T>为同一T作为类。

表明这一点的最好办法是改变略微类:

public class OpenGenericWithOpenService<T1, T2> : IGenericService<T1> {} 

现在,这一点很重要,当你问它实现的接口,你知道你可以转换为IGenericService<T1>但(巧合一边)不是IGenericService<T2>或任何其他实现。

换句话说,它不是完全开放的 - 它被固定在与类相同的类型参数上。

我从来没有很好的泛型术语,但我希望你明白我的意思。 IGenericService<>是一个等待被赋予类型参数的类型;在这种情况下,你的得到了的类型参数 - 它恰好是另一个类型参数!

这是一个测试将通过:

[TestMethod] 
public void can_get_open_generic_interface_off_of_implementor() 
{ 
    Type[] typeParams = typeof(OpenGenericWithOpenService<>).GetGenericArguments(); 
    Type constructed = typeof(IGenericService<>).MakeGenericType(typeParams); 
    typeof(OpenGenericWithOpenService<>).GetInterfaces().First()    
     .ShouldEqual(constructed); 
} 

如果更改类来实现(比方说)IGenericService<int>相反,它会失败。

+0

是的。刚刚在这里发现更多:http://stackoverflow.com/questions/511620/generic-types-not-equal 如果我使用typeof(OpenGenericWithOpenService <>)。GetInterfaces()。First()。 GetGenericTypeDefinition()' – 2010-04-20 20:35:16

+0

仍然不明白为什么'OpenGenericWithOpenService <>'没有实现'IGenericService <>'...? – thecoop 2010-04-20 20:35:18

+0

太棒了!我发现关于泛型的反射语义(开放或其他)的推理很复杂。我认为这个问题值得在一本书中处理。嗯,我们知道谁可以做到这一点...... :) – LBushkin 2010-04-20 20:37:32

相关问题