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.

Foi útil?

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
    }
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top