2011-10-19 18 views
9

Sto provando a iniettare un IEnumerable in un costruttore con Ninject.Iniezione di un oggetto IEnumerable in un costruttore con un metodo factory Ninject

mio costruttore si presenta così:

public MatrixViewModel(IEnumerable<FooViewModel> fooViewModels) 
{ 
    _fooViewModels = fooViewModels; 
} 

modulo mio Ninject si presenta così:

public class MainModule : NinjectModule 
{ 
    public override void Load() 
    { 
     Bind<IEnumerable<FooViewModel>>() 
      .ToMethod(context => GetFooViewModels()) 
      .InSingletonScope(); // this binding is not working 
    } 

    private IEnumerable<FooViewModel> GetFooViewModels() 
    { 
     // returns a bunch of foo view models 
    } 
} 

Questo non sembra funzionare. Non ho alcun errore. Ninject non usa mai l'associazione e il valore che viene passato al costruttore è fondamentalmente solo un valore predefinito vuoto.

Come si inietta uno IEnumerable con Ninject?

Modifica

Maggiori dettagli sul mio metodo di fabbrica:

private IEnumerable<FooViewModel> GetFooViewModels() 
{ 
    return new[] 
    { 
     new FooViewModel 
     { 
      Bar = new BarViewModel 
      { 
       X = 1, 
       Y = 2 
      }, 
      Misc = "Hello" 
     }, 
     new FooViewModel 
     { 
      Bar = new BarViewModel 
      { 
       X = 3, 
       Y = 4 
      }, 
      Misc = "Goodbye" 
     }, 
     // etc..... 
    }; 
} 

Edit 2

Sulla base di risposta di Remo, una possibile soluzione è quella di utilizzare un ciclo foreach di impegnare la visualizza i modelli uno alla volta:

foreach (var fooViewModel in GetFooViewModels()) 
{ 
    Bind<FooViewModel>().ToConstant(fooViewModel); 
} 
+1

non sono certo il supporto di raccolta o 'ToMethod' funziona in questo modo. Questo dovrebbe funzionare comunque: 'Bind (). ToMethod (context => new MatrixViewModel (GetFooViewModels()))'. Inoltre, puoi aggiungere la tua risposta alla tua domanda e accettarla se Remo non era abbastanza al livello che avresti voluto accettare come risposta. –

+0

@Merlyn, questo è un buon punto ... semplicemente "salire di livello" e associare l'intero MatrixViewModel (il mio modello di visualizzazione reale ha alcuni parametri, quindi sarebbe un po 'più di lavoro per legare tutto). Per quanto riguarda il motivo per cui non ho messo la mia soluzione in una risposta, potrei chiederti la stessa cosa sul tuo commento :) – devuxer

+0

Vero :) Ci sono sicuramente più soluzioni valide per questo ... –

risposta

5

Sulla base di risposta di Remo, una possibile soluzione è quella di utilizzare un ciclo foreach per legare i modelli vista una alla volta:

foreach (var fooViewModel in GetFooViewModels()) 
{ 
    Bind<FooViewModel>().ToConstant(fooViewModel); 
} 
+0

Questo dovrebbe fare lo stesso del bind originale, tranne che GetFooViewModels() viene chiamato nel momento in cui vengono creati i bind e nel bind originale viene chiamato quando viene risolto la prima volta. –

+0

Remo, l'altra differenza rispetto al mio binding originale è che questo funziona davvero :) Ma grazie per il follow-up. – devuxer

+0

@Remo: ho avuto l'impressione che NInject collezioni con involucro speciale, quindi risolverebbe tutti i binding del tipo nella raccolta. E se fosse un caso speciale, non sarei sorpreso se * non * risolvesse il contrario. Il comportamento nell'OP sembra corrispondere alla mia ipotesi. https://github.com/ninject/ninject/wiki/Multi-injection –

14

Gli oggetti numerici sono trattati in modo diverso da Ninject. Fornisci solo associazioni per tutti i modelli di visualizzazione. Per gli enumerabili, Ninject creerà un'istanza di ogni binding di applicazione e li passerà come IEnumerable.

ad es.

Bind<FooViewModel>().To<FooViewModel1>(); 
Bind<FooViewModel>().To<FooViewModel2>(); 
+0

Remo, grazie per la tua risposta, ma in realtà non affronta la mia situazione.Il mio metodo factory restituisce una serie di istanze di FooViewModel, non un gruppo di oggetti che ereditano da FooViewModel. – devuxer

+0

Vedi la mia modifica. – devuxer

+0

Attualmente non è possibile utilizzare i binding per IEnumerable, IList, List e array perché sono gestiti appositamente. Sfortunatamente devi lavorare un po 'usando un ICollection o derivando la tua interfaccia da IEnumerable

3

Dalla tua domanda:

Bind<IEnumerable<FooViewModel>>() 
    .ToMethod(context => GetFooViewModels()) 

non sono certo il supporto di raccolta o ToMethod funziona in questo modo.

Questo dovrebbe funzionerebbe comunque:

Bind<MatrixViewModel>() 
    .ToMethod(context => new MatrixViewModel(GetFooViewModels())) 

Naturalmente, quanto sia utile questa soluzione è dipende da come si sta costruendo le vostre opinioni.

+0

Stai iniettando nel tuo modello di vista, quindi questo non si applica alla tua situazione. Ma se stai usando WPF/MVVM, e provi ad iniettare il modello di vista nella vista, mi piace rimuovere qualsiasi concetto di modello di vista dalla mia vista e semplicemente impostare 'DataContext' della vista in' ToMethod'. –

+0

+1. Buona risposta ... potrei davvero andare con questo. – devuxer

Problemi correlati