2010-06-23 7 views
14

Considérons le code suivant. Lorsque je tente d'exécuter le programme, j'obtiens l'exception suivante.Inject Array of Interfaces in Ninject

Erreur activation IFoo
Aucune liaison de correspondance sont disponibles et le type ne sont pas auto-liables.
chemin d'activation:
2) L'injection de dépendance IFoo dans le paramètre foos du constructeur de type Bar
1) Demande de Bar

Comment puis-je injecter/lier à un tableau dans Ninject?

Merci pour votre temps.

Edit:
Mes importations d'application des données qui sont créées par un composant tiers. Le processus d'importation applique différents types de filtres (par exemple des implémentations de différentes interfaces de filtrage). Les règles de filtrage changent assez souvent mais sont trop complexes pour être effectuées avec une configuration pure (et un filtre maître).

Je veux rendre l'ajout/modification de filtres aussi facile que possible. Ce que j'ai est un assembly où toutes les implémentations de filtre sont situées. J'ai essayé de lier chaque interface de filtre à la méthode suivante (qui fournit une instance de chaque implémentation de ce type de filtre). Fondamentalement je veux éviter le besoin de changer mon module Ninject quand j'ajoute/enlève des classes de filtre. Je me sens un peu coupable en termes de contournement du mécanisme DI des conteneurs. Est-ce une mauvaise pratique? Y a-t-il une pratique courante pour faire de telles choses?

Résolution:
J'utilise une classe wrapper comme bsnote suggéré.

Répondre

7

Ceci est en grande partie une reformulation de la réponse de @ bsnote (que j'ai + 1d) qui peut aider à comprendre pourquoi cela fonctionne de cette manière.

Ninject (et d'autres DI/cadres Addin) ont deux installations distinctes:

  1. la notion de non contraignante à une seule mise en œuvre sans ambiguïté d'un service (Get)
  2. Une installation qui permet à un pour obtenir un ensemble de services [que l'on choisit alors un programme ou agrégats à travers d'une certaine façon] (GetAll/ResolveAll dans Ninject)

Votre code exemple arrive à utiliser sy ntax associée à 2. ci-dessus. (par exemple., dans MEF, on utilise généralement [ImportMany] annotations pour le rendre clair)

J'ai besoin de regarder dans les échantillons (regardez la source - c'est vraiment court, propre et facile à suivre) pour trouver une solution de contournement pour cela.

Cependant, comme @bsnote dit, une façon de refactorisation votre exigence est d'envelopper le tableau soit dans un récipient, ou d'avoir un objet qui vous le demandez (c.-à une méthode de fabrication ou de construction de type référentiel)

Il peut également être utile pour vous d'expliquer ce qu'est votre cas réel - pourquoi y a-t-il un tableau nu? Sûrement il y a une collection d'articles qui mendient à encapsuler sous-jacente à tout cela - cette question ne vient certainement pas beaucoup?

EDIT: Il y a un ensemble d'exemples d'analyse dans les extensions qui, j'imagine, attaqueraient beaucoup de choses que vous essayez de faire (dans des choses comme StructureMap, ce genre de choses est plus intégré, et contre). Selon que vous essayez d'obtenir ou non la convention par rapport à la configuration, vous pouvez envisager de coller une interface de marqueur sur chaque type de plug-in. Ensuite, vous pouvez explicitement Bind chacun. Alternativement, pour CoC, vous pouvez faire la boucle de routine de Module sur l'ensemble des implémentations que vous générez (c'est-à-dire beaucoup de Get s individuels) dans votre édition.

De toute façon, lorsque vous avez plusieurs enregistrements en place, vous pouvez soit 'demander' un T[] ou IEnumerable<T> et obtenir l'ensemble complet. Si vous voulez y parvenir explicitement (c'est-à-dire Service Locator et tout ce que cela implique - comme vous le faites, vous pouvez utiliser GetAll pour les traiter par lot de façon à ce que la boucle ne soit pas implicite comme vous l'avez fait.

Je ne sais pas si vous avez fait cette connexion ou si je manque quelque chose ou l'autre manière, je l'espère, il vous a appris à coller du code dans des questions comme il parle> 1000 mots:. P

+0

Je choisis ce que la réponse car il est plus détaillée. Merci (+1) à bsno te aussi! –

4

C'était aussi un problème pour moi. Ninject injecte chaque élément d'un tableau au lieu du tableau lui-même, vous devez donc avoir un mappage défini pour le type d'éléments du tableau. En fait, il n'y a aucune possibilité de mapper le tableau en tant que type avec la version actuelle de Ninject. La solution consiste à créer un wrapper autour du tableau. La classe paresseuse peut être utilisée par exemple si cela vous convient. Ou vous pouvez créer votre propre wrapper.

9

Ninject multi-supports injection qui résoudrait votre problème. https://github.com/ninject/ninject/wiki/Multi-injection

public interface IFoo { } 
public class FooA : IFoo {} 
public class FooB : IFoo {} 

public class Bar 
{ 
    //array injected will contain [ FooA, FooB ] 
    public Bar(IFoo[] foos) { } 
} 

public class MyModule : NinjectModule 
{ 
    public override void Load() 
    { 
     Bind<IFoo>().To<FooA>(); 
     Bind<IFoo>().To<FooB>(); 
     //etc.. 
    } 
}