2009-06-17 12 views
9

A menudo me encuentro en una situación en la que creo una interfaz o clase genérica y luego quiero usar diferentes versiones de esta clase o interfaz de una manera no genérica. Por ejemplo, puedo tener una interfaz como esta:Versiones no genéricas de clases e interfaces genéricas

interface ICanCreate<T> 
{ 
    T NewObject(); 
} 

Lo que permite que una clase sea una fábrica para ese tipo. entonces yo quiero registrar estos con una clase general de la fábrica, así que trato de escribir algo como esto:

public class Factory 
{ 
    private Dictionary<Type, ICanCreate> mappings; // what do I put here???? 

    public void RegisterCreator<T>(ICanCreate<T> creator) 
    {    
    } 

    public T Create<T>() 
    {    
    } 
} 

En el diccionario qué tipo debo usar para mi valor? No sé si me falta algún tipo de principio de diseño y soy consciente de que esto tiene mucho que ver con la varianza co (ntra?). Cualquier ayuda o ideas sería muy apreciada.

Respuesta

11

O lo que sólo tiene que utilizar object en su declaración diccionario (todo es privado y que puede verificar que usted nunca se pone el tipo equivocado de hora de allí) o declarar una interfaz no genérico ICanCreate cuales ICanCreate<T> se extiende.

Básicamente, desea una relación de tipo que no se puede expresar en C# - y cada vez que eso sucede, termina con una solución ligeramente desagradable, pero parece que puede aislar la fealdad aquí (es decir, mantenerlo dentro del único clase).

+0

¿Cuál diría usted que es el más preferido uno de los dos? Siempre busco la solución número dos si estoy en esta situación, porque creo que es una solución más elegante. Es, o no importa? – Razzie

+2

¿Hay algún miembro que pueda poner razonablemente en la interfaz no genérica? Si la interfaz es * solo * el método Create, entonces me quedaría con el objeto: la interfaz no genérica en realidad no te daría nada. En otros casos, es posible que pueda salirse con la suya solo haciendo referencia a la interfaz no genérica donde no conoce el argumento de tipo correcto, en cuyo caso eso proporciona un beneficio obvio. –

+0

¡Claro, gracias por el comentario! – Razzie

3

Curiosamente, este es un problema que se resuelve en C# 4.0:

public interface ICanCreate<out T> // covariant 
{ 
    T NewObject(); 
} 

public class Factory 
{ 
    private Dictionary<Type, ICanCreate<object>> mappings = new Dictionary<Type, ICanCreate<object>>(); 

    public void RegisterCreator<T>(ICanCreate<T> creator) where T:class 
    {    
     mappings[typeof(T)] = creator; 
    } 

    public T Create<T>() 
    {    
     ICanCreate<object> creator = mappings[typeof(T)]; 
     return (T) creator.NewObject(); // I do not think you can get rid of this cast 
    } 
} 
+0

¿Qué significa 'out T'? – Svish

+0

@Svish: Marca T como covariante. –

+0

Hm ... ¿qué significa eso? ¿Tienes un enlace con más información sobre eso o algo? – Svish

Cuestiones relacionadas