2010-01-28 13 views
7

Je vais avoir quelque chose comme ceci:valeur injectez dans la dépendance injectée

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

Et je suis en train d'obtenir une référence à la racine en utilisant ninject. donc je configure comme ça

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

var kernel = new StandardKernel(module); 

Je voudrais injecter dans la dépendance une valeur « val » qui est connu seulement au moment d'obtenir la référence racine de ninject.

Ce que je voudrais faire est quelque chose comme ceci:

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

Est-ce quelque chose comme ceci possible en utilisant ninject 1.0?

Répondre

8

Le Parameters.ConstructorArgument dans le contexte ne dépasse qu'une profondeur par défaut. Un moyen de passer des paramètres à plusieurs niveaux est d'utiliser un ContextParameter, mais quelque chose doit alors saisir cela et dire - et maintenant nous allons l'utiliser comme un ConstructorArgument dans ce cas. Une telle construction est fournisseurs. Voir this dojo page for details of Providers

Vous pouvez faire:

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)); 
    } 

Ou vous pouvez le gérer comme suit:

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)); 
    } 

Alors que vous pensez à cela, pensez the points I make in this point re separating the concerns if configuration from object binding in this response.

+0

Je pense que je pourrais le faire un peu plus simplement comme: Bind () .Pour() .WithConstructorArgument ("val", (IContext suite) => \t \t cont.ParentContext.Parameters. Récupère ("val")); Mais je n'aime pas utiliser le ParentContext. :(It – Silviu

+0

@Silviu: Essayez-le - le plus court le mieux, il semblait logique pour moi de faire directement ce que vous demandiez, mais je ne pouvais pas le faire travailler pour moi dans le contexte que je l'essayais –

+0

@ Silviu: Est-ce que vous l'avez fait dans le cadre du 'Bind' de travail? Si oui, si vous voulez chuck quelque chose qui fonctionne dans les commentaires, je vais le mettre dans les exemples –

1

Avec 3 Ninject IParameter s (ConstructorArgument est l'un d'entre eux) va maintenant être simplement « hérité » à la demande de l'enfant quand ils ont ShouldInherit == true (voir here).

La solution à cette question peut maintenant être aussi simple que:

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

où comme true dans le constructeur de l'ConstructorArgument définit ShouldInherit à true. Voir aussi here