Question

Je me trouve souvent dans une situation où je crée une interface ou une classe générique, puis que je souhaite utiliser différentes versions de cette classe ou de cette interface de manière non générique. Par exemple, je peux avoir une interface comme celle-ci:

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

Ce qui permet à une classe d'être une fabrique pour ce type. Je souhaite ensuite les enregistrer dans une classe de fabrique générale. J'essaie donc d'écrire quelque chose comme ceci:

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

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

    public T Create<T>()
    {            
    }
}

Dans le dictionnaire, quel type dois-je utiliser pour ma valeur? Je ne sais pas si il me manque une sorte de principe de conception et je suis conscient que cela a beaucoup à voir avec la co (ntra?) Variance. Toute aide ou idée serait très appréciée.

Était-ce utile?

La solution

Vous devez soit simplement utiliser objet dans votre déclaration de dictionnaire (tout est privé et vous pouvez vérifier que vous n'y mettez jamais le mauvais type ) ou déclarer une interface ICanCreate non générique que ICanCreate < T > étend.

En gros, vous voulez une relation de type qui ne puisse pas être exprimée en C # - et à chaque fois que cela se produit, vous vous retrouvez avec une solution légèrement déplaisante, mais il semble que vous puissiez isoler la laideur ici (c'est-à-dire la conserver dans la même classe ).

Autres conseils

Fait intéressant, c’est un problème qui est résolu 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
    }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top