Here's a test that should, in my opinion be passing but is not.
[TestMethod]
public void can_get_open_generic_interface_off_of_implementor()
{
typeof(OpenGenericWithOpenService<>).GetInterfaces().First()
.ShouldEqual(typeof(IGener开发者_如何学JAVAicService<>));
}
public interface IGenericService<T> { }
public class OpenGenericWithOpenService<T> : IGenericService<T> { }
- Why does this not pass?
- Given
Type t = typeof(OpenGenericWithOpenService<>)
how do I get typeof(IGenericService<>)?
I'm generally curious, but if you're wondering what I'm doing, I'm writing a Structuremap convention that forwards all interfaces implemented by a class to the implementation (as a singleton).
OpenGenericWithOpenService<T>
doesn't implement just an arbitrary IGenericService<>
- it implements IGenericService<T>
for the same T
as the class.
The best way to show this is to change the class slightly:
public class OpenGenericWithOpenService<T1, T2> : IGenericService<T1> {}
Now it's important that when you ask that for the interfaces it implements, you know that you can convert to IGenericService<T1>
but (coincidences aside) not IGenericService<T2>
or any other implementation.
In other words, it's not entirely open - it's pinned down to the same type argument that the class has.
I've never been very good with the generics terminology, but I hope you see what I mean. IGenericService<>
is a type waiting to be given a type argument; in this case you've got the type argument - it just happens to be another type parameter!
Here's a test which will pass:
[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);
}
If you change the class to implement (say) IGenericService<int>
instead, it will fail.
精彩评论