2010-01-28 5 views
7

Sto avendo qualcosa di simile:valore Iniettare in dipendenza iniettato

class Root 
{ 
    public Root(IDependency dep) 
    {} 
} 
class Dependency:IDependency 
{ 
    public Dependency(int val) 
    {} 
} 

E io sto cercando di ottenere un riferimento a root usando Ninject. Così ho configurato in questo modo

var module = new InlineModule(mod => mod.Bind<IDependency>().To<Dependency>()); 

var kernel = new StandardKernel(module); 

mi piacerebbe iniettare in dipendenza qualche valore 'val' che è nota solo al momento di ottenere il riferimento principale da Ninject.

Quello che mi piacerebbe fare è qualcosa di simile:

Kernel.Instance.Get<Root>(With.Parameters.ConstructorArgument("val", 12)); 

è qualcosa di simile possibile utilizzando Ninject 1.0?

risposta

8

Il Parameters.ConstructorArgument nel contesto è impostato su un livello solo per impostazione predefinita.

Un modo per passare i parametri su più livelli consiste nell'utilizzare un ContextParameter, ma in questo caso è necessario afferrare ciò e dire - e ora lo useremo come strumento Costruttore in questo caso. Uno di questi costrutti è Provider. Vedere this dojo page for details of Providers

modo da poter fare:

class DependencyProvider : SimpleProvider<Dependency> 
    { 
     protected override Dependency CreateInstance(IContext context) 
     { 
      return new Dependency((int)context.ParentContext.Parameters.GetOne<ContextVariableParameter>("masterVal").Value); 
     } 
    } 

    public static void Main() 
    { 
     var module = new InlineModule(
      mod => mod.Bind<IDependency>().ToProvider(new DependencyProvider()) 
     ); 

     var kernel = new StandardKernel(new[ ] {module}); 

     Root root = kernel.Get<Root>(With.Parameters.ContextVariable("masterVal", 12)); 
    } 

Oppure si può gestirlo come segue:

class RootProvider : SimpleProvider<Root> 
    { 
     protected override Root CreateInstance(IContext context) 
     { 
      return new Root(context.Kernel.Get<Dependency>(With.Parameters.ConstructorArgument("val", (int)context.Parameters.GetOne<ContextVariableParameter>("masterVal").Value))); 
     } 
    } 

    public static void Main() 
    { 
     var module = new InlineModule(
      mod => mod.Bind<IDependency>().To<Dependency>(), // Optional if ImplictSelfBinding is on 
      mod => mod.Bind<Root>().ToProvider(new RootProvider()) 
     ); 

     var kernel = new StandardKernel(new[] {module}); 

     Root root = kernel.Get<Root>(With.Parameters.ContextVariable("masterVal", 12)); 
    } 

Mentre si sta pensando a questo, si consideri the points I make in this point re separating the concerns if configuration from object binding in this response.

+0

credo che avrei potuto fare un po 'più semplicemente come: Bind () .Per () .WithConstructorArgument ("val", (IContext cont) => \t \t cont.ParentContext.Parameters. ottenere ("val")); Ma non mi piace usare ParentContext. :(It – Silviu

+0

@Silviu: Provalo - il più breve è il migliore, mi sembrava che avesse senso direttamente come quello che stavi chiedendo, ma non riuscivo a farlo funzionare nel contesto in cui lo stavo provando .. –

+0

@ Silviu: L'hai fatto come parte del lavoro di 'Bind'? Iff quindi, se vuoi inserire qualcosa che funzioni nei commenti, lo inserirò negli esempi. –

1

Con Ninject 3 IParameter s (ConstructorArgument è uno di loro) sarà ora essere semplicemente "ereditato" la richiesta del bambino quando hanno ShouldInherit == true (vedi here).

La soluzione per questo problema può ora essere semplice come:

IResolutionRoot.Get<Root>(new ConstructorArgument("val", 12, true)); 

dove come l'true nella ConstructorArgument s costruttore imposta ShouldInherit a true. Vedere anche here