2010-08-30 10 views
1

Je commence juste avec l'injection de dépendance. J'ai lu le wiki Ninject et sa façon très claire d'injecter des dépendances où une seule instance de la dépendance est requise, en utilisant l'injection de constructeur, de propriété ou de méthode. Mais comment gérez-vous le cas où votre classe a besoin de construire des objets au cours de sa vie (après la construction)? Par exemple:Ninject - comment injecter pendant la durée de vie de l'objet?

class AddressBook 
{ 
    private List<IContact> _contacts; 

    public AddContact(string name) 
    { 
     _contacts.Add(****what?****) 
    } 
} 

La seule façon que je peux penser est d'utiliser l'injection de constructeur pour passer dans un IKernel et l'utiliser pour obtenir notre IContact:

class AddressBook 
{ 
    private IKernel _kernel; 
    private List<IContact> _contacts; 

    public AddressBook(IKernel kernel){ _kernel = kernel; }   

    public AddContact(string name) 
    { 
     _contacts.Add(_kernel.Get<IContact>(new Parameter("name", name))); 
    } 
} 

Mais comment pouvez-vous injecter le noyau? ? Quelle cartographie serait nécessaire? Est-ce la même approche?

Merci pour toute aide felix

Répondre

1

La réponse comme suggéré par Benjamin Podszun:

Injecter une usine:

public interface IContactFactory 
{ 
    IContact CreateContact(string name); 
} 

class AddressBook 
{ 
    private IContactFactory _factory; 
    private List<IContact> _contacts; 

    public AddressBook(IContactFactory factory){ _factory = factory; }   

    public AddContact(string name) 
    { 
     _contacts.Add(_factory.CreateContact(name)); 
    } 
} 

Ensuite, vous pouvez lier l'usine à tout ce que vous voulez créer une instance spécifique de IContact.

+0

Oui, c'est comme ça que je le ferais. http://kozmic.pl/archive/2010/06/22/how-i-use-inversion-of-control-containers-ndash-pulling-from.aspx –

0

Vous pouvez le faire assez proprement avec: (exec summary of another answer re a slightly different question)

Bind<Func<IContact>>().ToMethod(context =>() => Kernel.Get<Contact>()); 

Vos autres options sont:

  • ont un IKernel injecté que vous avez fait (qui est pris en charge OOTB avec des trucs spéciaux) , mais comme vous en parlez, c'est rarement ce que vous voulez - cela équivaut à un emplacement de service.

  • Faire une usine en vraie grandeur. Voir l'autre réponse pour la manière idiomatique Ninject (un fournisseur) de faire plus ou moins ce que votre réponse à soi-même dit. Vous feriez mieux d'avoir une bonne raison de faire cette quantité de plaque de chaudière bien.

2

similaires à ce que les autres ont répondu, nous utilisons une interface IFactory générique:

public interface IFactory<T> 
{ 
    T Get(); 
} 

qui peut être utilisé comme ceci:

public AddressBook(IFactory<IContact> ContactFactory) 

Et puis mis en œuvre comme ceci:

public class InjectorFactory : IFactory<T> 
{ 
    // we wrapped the Kernel in an Injector class 
    public T Get() { return Injector.Get<T>(); } 
} 

Et lié l comme ceci:

Bind(typeof(IFactory<>)).To(typeof(InjectorFactory<>)) 

Cela a très bien fonctionné pour nous jusqu'ici.

+0

+1 Nice. Je suis assez sûr de faire un 'Bind (typeof (Func <>)). ToMethod (contexte =>() => contexte.Get (contexte.Service))' fonctionnerait aussi (bien que j'irais probablement avec le vôtre en tant que c'est gentil et explicite). En outre, si les gens sont intéressés, il y a quelques tests/échantillons dans la source re génériques ouverts de liaison comme ceci. –

+0

Ouais, lier un Func vous permettrait d'ignorer l'interface et de faciliter les tests. Nous avons fini par implémenter 'FunctionBasedFactory' pour que nous puissions simplement utiliser un Func pour injecter des usines dans les tests unitaires. Mais je préfère utiliser une interface pour les dépendances. – StriplingWarrior