Versioni non generiche di classi e interfacce generiche
-
05-07-2019 - |
Domanda
Spesso mi trovo in una situazione in cui creo un'interfaccia o una classe generica e quindi voglio utilizzare versioni diverse di questa classe o interfaccia in modo non generico. Ad esempio potrei avere un'interfaccia come questa:
interface ICanCreate<T>
{
T NewObject();
}
Che consente a una classe di essere una factory per quel tipo. Voglio quindi registrarli con una classe factory generale, quindi provo a scrivere qualcosa del genere:
public class Factory
{
private Dictionary<Type, ICanCreate> mappings; // what do I put here????
public void RegisterCreator<T>(ICanCreate<T> creator)
{
}
public T Create<T>()
{
}
}
Nel dizionario quale tipo devo usare per il mio valore? Non so se mi manca una sorta di principio di progettazione e sono consapevole che questo ha molto a che fare con la varianza co (ntra?). Qualsiasi aiuto o idea sarebbe molto apprezzato.
Soluzione
Devi solo usare object
nella tua dichiarazione del dizionario (è tutto privato, e tu puoi verificare che non ci metterai mai il tipo sbagliato di cose) o dichiarare un non -generica ICanCreate
interfaccia che ICanCreate<T>
estende.
Fondamentalmente vuoi una relazione di tipo che non può essere espressa in C # - e ogni volta che succede, ti ritrovi con una soluzione leggermente spiacevole, ma sembra che tu possa isolare la bruttezza qui (cioè tenerlo all'interno della singola classe ).
Altri suggerimenti
È interessante notare che questo è un problema risolto in 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
}
}