2009-11-19 6 views
0

Je suis intéressé par la mise en œuvre d'un conteneur IoC dans mon projet, mais je n'ai pas vu un exemple qui fasse ce dont j'ai besoin.Objet de conteneur IoC portée

Voici la situation, mon application est construite en WPF et utilise le modèle MVVM pour créer un lecteur pour un format vidéo infrarouge. Dans ce format, chaque vidéo est composée de plusieurs "sous-images" (pensez-y comme capturant simultanément plusieurs vitesses d'obturation afin d'augmenter la plage dynamique des données) qui sont affichées dans un TabControl. Je voudrais utiliser un conteneur IoC pour m'aider à créer les ViewModels pour chacun des onglets, mais j'ai deux préoccupations.

  1. je besoin d'un moyen de passer dans l'objet qui représente le sous-cadre que je crée un ViewModel pour si au moins l'une des dépendances du ViewModel ne peut pas être créé par le conteneur IoC car il existe déjà.

  2. J'ai des contrôles utilisateur à l'intérieur de la vue pour une sous-trame qui ont leurs propres ViewModels, donc ces ViewModels doivent également être créés par le conteneur IoC. Le problème avec ceci est que tandis que les contrôles (et leurs ViewModels) ont des soucis séparés, ils ne sont pas complètement indépendants donc ils utilisent des objets de coordination. Malheureusement, dans tous les exemples que j'ai vus, vous pouvez avoir votre conteneur IoC créer une nouvelle instance d'une dépendance ou avoir un singleton, mais ce dont j'ai besoin est une seule instance pendant la période contrôlée lorsque je crée la sous-trame ViewModel .

Cela fait beaucoup de texte alors voici un code qui montre ce que je fais et ce que je voudrais faire.

Ce que j'ai maintenant

En plein air un code de film:

foreach (var subframe in movieFile) 
{ 
    // Subframes is the ObservableCollection that the TabControl is bound to 
    Subframes.Add(new SubframeViewModel(subframe)); 
} 

Dans le SubframeViewModel:

Ce que je voudrais avoir sans changer l'existant sematics

En plein air un code de film:

foreach (var subframe in movieFile) 
{ 
    Subframes.Add(container.Resolve<SubframeViewModel>()); 
} 

Dans le SubframeViewModel:

public SubframeViewModel(ISubframe subframe, ImageViewModel imageModel, 
          FrameControlViewModel frameModel) 
{ 
    _subframe = subframe; 

    ImageViewModel = imageModel; 

    FrameControlViewModel = frameModel; 
} 

En réalité, il y a plus de coordination et des objets ViewModel impliqués, mais les motifs sont les mêmes. Cela dit, je pense que vous pouvez voir pourquoi je suis intéressé par un conteneur IoC ici.

Je pense que mon scénario devrait être assez commun mais je ne suis pas sûr et je ne veux pas perdre mon temps à essayer d'insérer une cheville carrée dans un trou rond, voici donc mes questions. Est-ce que tous les conteneurs IoC peuvent le faire? Si non, pouvez-vous me diriger vers un refactoring qui améliorerait mon code et ferait fonctionner IoC?

Répondre

1

Autofac fait sans aucun doute ce que vous avez besoin - paramètres fournis peuvent explicitement être combinés avec ceux autowired par le conteneur:

vm = container.Resolve<SubFrameViewModel>(new NamedParameter("subframe", subframe)); 

(Correspondance par type plutôt que le nom est également possible.)

Vous pouvez même le conteneur injectent un délégué Func ou personnalisé dans le composant appelant, de sorte que la dépendance des conteneurs (ie l'appel à Resolve) est inutile:

Func<ISubFrame, SubFrameViewModel> _vmFactory; // Injected 
vm = _vmFactory(subframe); 

Voir http://code.google.com/p/autofac/wiki/DelegateFactories pour plus d'informations sur la dernier.

Nick

+0

Hmm aurait peut-être mal interprété votre question sur une deuxième lecture - HTH de toute façon! –

+0

Que cela réponde complètement ou non à toutes mes questions, maintenant je suis pointé dans la bonne direction. Je peux définitivement voir comment je peux tout faire fonctionner plus proprement avec ça. Merci pour l'aide. –

+0

En regardant les docs Autofac, il me semble que si j'ai créé un conteneur imbriqué pour chaque sous-trame et que FrameController est marqué ContainerScoped, tout ce que je devrais faire est d'utiliser ce que vous avez pour spécifier la sous-trame. Est-ce que cela semble être une chose raisonnable à faire? –

1

On dirait que vous voulez gérer les paramètres du constructeur supplémentaires dans votre scénario IoC, et je vois deux options:

1 - Création d'un simple constructeur qui prend dans une sous-trame, et d'exposer la ImageViewModel et FrameControlViewModel comme propriétés définissables publiques comme si:

// assumes frameControlVM and imageVM have been constructed and are valid 
foreach (var subframe in movieFile) 
{ 
    var subframeVM = container.Resolve<SubframeViewModel>(subframe); 
    subframeVM.ImageVM = imageVM; 
    subframeVM.FrameControlVM = frameControlVM ; 
    Subframes.Add(subframeVM); 
} 

2 - Faire passer les arguments dont vous avez besoin dans le conteneur IoC, qui passe simplement les paramètres dans le constructeur SubframeVM:En fin de compte, celui que vous choisissez dépend du couplage étroit que vous voulez que votre résolveur IoC SubframeViewModel soit avec le reste de vos machines virtuelles. Si votre imageVM et frameControlVMs besoin IOCs de leur propre, vous pouvez simplement les Enchaînez:

// assumes frameControlVM and imageVM have been constructed and are valid 
foreach (var subframe in movieFile) 
{ 
    var frameControlVM = container.Resolve<FrameControlViewModel >(subframe); 
    var imageVM = container.Resolve<ImageViewModel>(subframe, frameControlVM); 
    var subframeVM = container.Resolve<SubframeViewModel>(subframe, imageVM, frameControlVM); 
    Subframes.Add(subframeVM); 
} 
+0

Merci Micah, ça aide vraiment. Quel conteneur IoC utilisez-vous ici? –

+0

Je ne sais pas. :) J'ai roulé un custom il y a quelques années quand je devais faire aussi le chargement d'assemblages dynamiques en plus de l'instanciation de classe de style usine. Cependant, pour la plupart des petits projets que je fais, l'avantage de l'instanciation connectable via une configuration externe est moins important pour moi que la vérification de la compilation - et je n'aime pas deviner les interfaces et les classes abstraites à l'avance ; c'est quelque chose que j'épargne pour le refactoring. – micahtan