8
votes

Dictionnaire des types de classe

J'ai un ensemble de classes, chacun pouvant ouvrir différents types de fichiers à l'aide d'une application externe et indiquer cette application à imprimer le fichier à une imprimante particulière. Les classes ont tous hérité d'une classe abstraite commune et d'une interface. XXX

J'essaie de créer un dictionnaire des extensions de fichier imprimable et de type correspondant S de classes pouvant imprimer de tels fichiers. Je fais pas veulent instancier les classes du dictionnaire. xxx

est là un moyen de faire dictionnaire fileconverters plus de sécurité, en le limitant aux valeurs qui implémentent IAPPLLicationPritter? En d'autres termes, c'est quelque chose comme ça possible: xxx

mise à jour: Je ne veux pas stocker des instances pour les deux raisons suivantes:

  1. Chaque classe peut gérer plusieurs types de fichiers différents (voir chaîne [] imprimableextensions ). Le dictionnaire stocke des extensions comme des clés. Il n'y a pas d'utilitaire dans la création et le stockage de plusieurs séparations de la même classe.
  2. Chaque classe d'imprimante utilise COMP API et Office Interop pour créer des instances d'applications tierces. Il vaut mieux qu'une nouvelle instance de chaque classe soit créée pour un travail d'impression si nécessaire et que le collecteur des ordures peut nettoyer après.

1 commentaires

Pourquoi ne veulez-vous pas stocker des instances dans le dictionnaire?


4 Réponses :


3
votes

pas directement - rappelez-vous que les choses que vous mettez dans votre dictionnaire sont type objets, pas d'objets qui implémentent iapplicationPinter . .

Probablement la meilleure option ici consiste à vérifier que chaque type que vous ajoutez à votre dictionnaire implémente iipplicationPrinter , en vérifiant si type.geterface ("iapplicationPinter") retourne null ou pas.


3 commentaires

Je pense qu'il est préférable d'éviter les chaînes au lieu de types dans la mesure du possible. Et c'est possible ici.


Vous avez raison - typeof (IAPplicationPrinter) .name serait mieux que "IAPplicationPritter".


Je voulais dire quelque chose de plus dans les lignes de typeof (iappplicationPritter) .isAssignABLeFrom (type) . Complètement sûr et sans cordes utilisées.



1
votes

Si vous avez utilisé Dictionnaire , qui ne signifie pas que vous devrez avoir une instance différente pour chaque chaîne , plusieurs d'entre eux peuvent partager la Même exemple.

Si vous ne voulez pas faire cela, vous pouvez stocker des usines dans le dictionnaire. L'usine peut être un objet qui implémente une interface (quelque chose comme iappplicationPinterfactory ) ou juste un délégué pouvant créer l'objet. Dans votre cas, ce serait Dictionnaire > . Le fait de cette façon est complètement sûr. Pour ajouter au dictionnaire, vous feriez quelque chose comme: xxx

si vous voulez que vous souhaitiez dictionnaire , il y a aucun moyen de limiter cela, de sorte que tous les types d'exécution implémentent iapplicationprinter . Ce que vous pouviez faire est de créer votre propre dictionnaire, qui vérifie le type lors de l'addition. Cela ne fait pas de sécurité en sécurité de la compilation, mais cela le rend plus sûr de l'heure d'exécution. xxx


0 commentaires

6
votes

Je le ferais légèrement différemment:

private Dictionary<String, Func<IApplicationPrinter>> _converters;

public void Initialise()
{
    foreach (string ext in WordPrinter.PrintableExtensions)
    {
        _converters.Add(ext, () => new WordPrinter());
    }
}

public IApplicationPrinter GetPrinterFor(String extension)
{
    if (_converters.ContainsKey(extension))   //case sensitive!
    {
        return _converters[extension].Invoke();
    }

    throw new PrinterNotFoundException(extension);
}


1 commentaires

Je cherchais cette solution! Merci Pondidum, pas besoin de plus besoin d'un énorme si () nouveau a (); sinon si () nouveau b (); sinon si () nouveau c (); sinon si () Nouveau ... dans mon code.



0
votes

Vous devez d'abord modifier votre approche pour accéder au tableau d'extensions car vous ne pouvez pas accéder à votre propriété sans créer d'instance. J'utiliserais une personnalisation attribut à Dites à votre dictionnaire de type quelle extension chaque classe prend en charge. Cela ressemblera à ceci: xxx

à l'aide de l'attribut vous permet de restreindre le type. Il y a deux façons d'archiver cela.

  • lancer une exception dans le constructeur du type (voir Ce lien )
  • Utilisez une classe abstrait au lieu d'une interface, cela vous permet de restreindre votre classe en utilisant un attribut protégé (à ce stade, vous devez créer une classe de base pour l'attribut pour y accéder à partir de votre dictionnaire type) qui ne peut être que appliqué aux classes déviées.

    Vous pouvez désormais simplement vérifier si une classe particulière possède l'attribut PrintÉextensions et accédez à une propriété qui récupère toutes les extensions ou appelez une méthode qui enregistre directement toutes les extensions.


0 commentaires