As versões não genéricas de Classes genéricas e interfaces
-
05-07-2019 - |
Pergunta
Muitas vezes eu me encontrar em uma situação onde eu criar uma interface genérica ou classe e depois quiser usar diferentes versões desta classe ou interface de uma forma não genérico. Por exemplo, eu possa ter uma interface como este:
interface ICanCreate<T>
{
T NewObject();
}
O que permite que uma classe para ser uma fábrica para esse tipo. Eu, então, pretende registar estas com uma classe de fábrica geral, então eu tento escrever algo como isto:
public class Factory
{
private Dictionary<Type, ICanCreate> mappings; // what do I put here????
public void RegisterCreator<T>(ICanCreate<T> creator)
{
}
public T Create<T>()
{
}
}
No dicionário qual o tipo que eu uso para o meu valor? Eu não sei se eu estou faltando algum tipo de princípio de design e estou ciente de que isso tem muito a ver com co (ntra?) Variância. Qualquer ajuda ou idéias seria muito apreciado.
Solução
Você tem que object
uso apenas em sua declaração de dicionário (que é tudo privado e você pode verificar que você nunca vai colocar o tipo errado de coisa lá dentro) ou declarar um não-genéricos Interface ICanCreate
que ICanCreate<T>
estende.
Basicamente você quer um relacionamento tipo que não pode ser expresso em C # - e sempre que isso acontece, você acaba com uma solução ligeiramente desagradável, mas parece que você pode isolar a feiúra aqui (ou seja, mantê-lo dentro da mesma classe ).
Outras dicas
Curiosamente, este é um problema que é resolvido em 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
}
}