2010-04-20 23 views
10

Aquí hay una prueba que, en mi opinión, debería aprobar, pero no es así.¿Los tipos de interfaz genérica abierta de implementación abierta no son iguales al tipo de interfaz?

[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. ¿Por qué esto no pasa?
  2. Dado Type t = typeof(OpenGenericWithOpenService<>) ¿cómo obtengo typeof (IGenericService <>)?

En general tengo curiosidad, pero si se está preguntando qué estoy haciendo, estoy escribiendo una convención de Structuremap que reenvía todas las interfaces implementadas por una clase a la implementación (como singleton).

+0

Pregunta crujiente. Investigación :) –

+0

Si realmente desea que pase la prueba, puede comparar los GUID. –

Respuesta

7

OpenGenericWithOpenService<T> no implementa sólo una arbitraria IGenericService<> - implementa IGenericService<T> para el mismo T que la clase.

La mejor manera de demostrar esto es cambiar la clase ligeramente:

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

Ahora es importante que cuando se pide que para las interfaces que implementa, usted sabe que usted puede convertir a IGenericService<T1> pero (coincidencias de lado) noIGenericService<T2> o cualquier otra implementación.

En otras palabras, no está del todo abierto; está anclado al mismo argumento de tipo que tiene la clase.

Nunca he sido muy bueno con la terminología de genéricos, pero espero que veas lo que quiero decir. IGenericService<> es un tipo que espera recibir un argumento de tipo; en este caso tiene tiene el argumento de tipo - ¡simplemente pasa a ser otro parámetro de tipo!

Aquí es una prueba que pasará:

[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); 
} 

Si cambia la clase para implementar (por ejemplo) IGenericService<int> lugar, se producirá un error.

+0

Sí. Acabo de encontrar más sobre esto aquí: http://stackoverflow.com/questions/511620/generic-types-not-equal La prueba pasa si uso 'typeof (OpenGenericWithOpenService <>). GetInterfaces(). First(). GetGenericTypeDefinition() ' –

+0

Todavía no entiendo por qué' OpenGenericWithOpenService <> 'no implementa' IGenericService <> '...? – thecoop

+0

Brillante! He descubierto que el razonamiento sobre la semántica de reflexión de los genéricos (abiertos o no) es complicado. Creo que el tema merece tratamiento en un libro. Hmmm, ¿quién sabemos que podría hacer eso ... :) – LBushkin

Cuestiones relacionadas