Peut-être que je mésapplique Unity, mais voilà. J'ai quelques applications, les deux chargeant les mêmes assemblys de plugin. Tous les assemblages nécessitent une bibliothèque et je veux qu'ils puissent accéder à cette bibliothèque via Unity. Cependant, pour utiliser Unity, ou tout autre framework IoC, je devrais écrire une interface pour cette bibliothèque. Je vais probablement le faire, mais comme une interface n'est pas vraiment nécessaire pour autre chose que de supporter Unity, j'ai peur que cela signifie que 1) je manque le point, ou 2) que j'applique mal le cadre. Si j'évite quelque chose qui m'offre DI, alors je devrais faire de la classe library un singleton, et ensuite le passer à tous les constructeurs de plugins, ou via une propriété publique, et je ne veux pas le faire. Cela dit, et sans réellement implémenter quoi que ce soit avec Unity, je ne reçois pas un autre détail - bien que Unity me laisse demander la bibliothèque via Resolve <>, mes plugins devront toujours avoir une référence à la Instance Unity créée dans les applications principales. Donc, est-ce un cas où votre seule option est de passer la référence Unity à tous les plugins, mais alors c'est pratique à partir de ce point, simplement parce que vous pouvez utiliser Unity pour obtenir toutes les autres dépendances?Y a-t-il quelque chose comme Unity pour des choses simples qui ne nécessitent pas d'interface?
MISE À JOUR
je réalisais que je manqué le point, mais nous espérons que quelqu'un peut me préciser - je ne devrais pas passer un arbitre à l'unité partout! Je devrais seulement créer le conteneur dans mon application, puis enregistrer tous les types par la suite. Puis, quand j'instancie tous mes plugins, ils devraient simplement pouvoir utiliser ces interfaces enregistrées, sans presque aucun effort, n'est-ce pas? Dans mon cas, mes constructeurs doivent être sans paramètre car mon plugin loader ne peut pas gérer les arguments, et dans ce cas, je vais devoir utiliser l'injection de propriété pour leur donner accès aux interfaces, n'est-ce pas?
une mise à jour
je suis allé de l'avant et essayé l'unité. J'ai enregistré l'instance de ma classe dont tous les plugins ont besoin. Je sais aussi que je finirais par rencontrer un problème avec mon chargeur de plugins car ils sont sans paramètre (et je pourrais avoir besoin de lui passer une référence à Unity pour les faire fonctionner). Cependant, juste pour l'instant je crée directement un plugin, et je le fais via la méthode Resolve. Voici donc essentiellement ce que le code ressemble à:
// app code
ICandySettings _candy_settings = new CandySettings();
IUnityContainer unity = new UnityContainer().RegisterInstance<ICandySettings>(_candy_settings);
CandyPlugin _plugin = unity.Resolve<Candy>(); // throws null reference exception, see below.
// plugin code
public class Candy
{
[Dependency]
ICandySettings CandySettings { get; set; }
...
public Candy()
{
CandySettings.GetSetting("box"); // CandySettings is null! why? Didn't Unity do this for me?
}
}
Donc mon problème est en ce moment que je me attends (compte tenu de ma connaissance limitée), que l'unité va mettre automagiquement la référence de CandySettings du plugin à quelque instance a été enregistré via RegisterInstance, mais ce n'est pas le cas.
UN GROUPE DE TRAVAIL OPTION
Si je saute les trucs de la fumée et des miroirs et juste passer mon UnityContainer dans le constructeur du plug-in, je peux appeler Unity.Resolve() pour définir la valeur de ma CandySettings propriété, et Tout fonctionne très bien. J'aimerais savoir pourquoi l'attribut [Dependency] ne fait pas ce que je pensais. Si je ne me trompe pas, je ne devrais pas vraiment besoin de passer Unity à chaque constructeur dans mon chargeur de plugin. Je devrais juste utiliser Unity.Resolve() et cela fonctionnerait probablement si [Dependency] fonctionne. Cependant, maintenant je comprends ce que tout le monde dit à propos de la façon dont le choix d'un conteneur IoC le forcera sur l'ensemble de votre équipe de développement.
MEF!
Jusqu'ici, MEF me gagne la bataille.C'est assez simple, et les trucs magiques de la fumée et des miroirs fonctionnent très bien pour mes besoins (actuellement). Mais j'aimerais quand même que Unity travaille. Je trouve étrange que pour MEF, je n'ai besoin que de composer les parties et tout le reste tombe en place, alors que je n'arrive pas à obtenir que Unity injecte simplement des choses automatiquement, et je dois Résoudre tout par une référence à Unity partout. Cela ne peut pas être juste.
Plus
MEFJ'aime l'idée que je peux résoudre plusieurs objets très facilement avec MEF, mais qu'en cas où j'utilise le modèle de stratégie pour dicter le comportement de code? Actuellement, c'est aussi simple que de changer la référence d'une implémentation d'un comportement à l'autre, et cela fonctionne fonctionne simplement. Est-ce que quelqu'un le fait avec MEF? Est-ce la bonne façon de le faire pour utiliser ImportMany, puis utiliser du code supplémentaire pour déterminer quel comportement dans la liste devrait être invoqué?
Je pense que le principe de conception de «programme à une interface, pas une mise en œuvre» a été prouvé pour ajouter de la valeur dans de nombreux cas. Je ne dirais pas que vous mettriez en œuvre les interfaces «juste pour l'unité». –
Je suis totalement d'accord, mais pour ce cas particulier, je ne vois pas comment une interface m'achète vraiment quelque chose. Là encore, j'allais dire "il n'y a aucun moyen de changer le backend d'une base de données", mais vous savez comment ça se passe ...;) – Dave
@Marvin: C'est vrai, mais il a également été démontré qu'il augmentait la complexité dans de nombreux cas. Les directives de conception de bibliothèque de classes de framework .NET disent en fait de préférer les classes abstraites aux interfaces (le cas échéant) puisqu'elles sont plus compréhensibles et plus faciles à découvrir. –