Pregunta

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:

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

Lo que permite que una clase sea una fábrica para ese tipo. Luego quiero registrarlos en una clase de fábrica general, 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 utilizo 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 variación de co (ntra?). Cualquier ayuda o idea sería muy apreciada.

¿Fue útil?

Solución

Tienes que usar object en la declaración de tu diccionario (todo es privado y puedes verificar que nunca pondrás el tipo incorrecto de cosas allí) o declarar un no -interfaz genérica ICanCreate que 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, mantenerla dentro de la clase única ).

Otros consejos

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
    }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top