2017-10-12 3 views
1

Je souhaite utiliser un motif de décorateur en utilisant Castle Windsor pour créer un modèle de vue pour mon API, mais en injectant différentes classes dans les décorateurs en fonction du contrôleur. J'ai deux versions de l'extrémité api.Modèle de décorateur utilisant Castle Windsor quand une classe différente doit être injectée en fonction de l'appelant

Un pour HomeV1Controller:

public class HomeV1Controller : ApiController { 
    private readonly IHomeViewModelFactory _factory; 

    public HomeV1Controller(IHomeViewModelFactory factory) { 
     _factory = factory; 
    } 
} 

et seconde:

public class HomeV2Controller : ApiController { 
    private readonly IHomeViewModelFactory _factory; 

    public HomeV2Controller(IHomeViewModelFactory factory) { 
     _factory = factory; 
    } 
} 

les deux contrôleurs accepte IHomeViewModelFactory dont il Definitions est:

public interface IHomeViewModelFactory { 
    HomeViewModel CreateViewModel(); 
} 

Je voudrais maintenant injecter modèle de vision commune usine pour les deux contrôleurs et cette usine ont besoin d'appeler la prochaine vie w usine de modèle qui est spécifique au contrôleur. Donc, j'ai usines:

communs:

public class UserViewModelFactory : IHomeViewModelFactory { 
    private readonly IHomeViewModelFactory _factory; 

    public UserViewModelFactory(IHomeViewModelFactory factory) { 
     _factory = factory; 
    } 

    public HomeViewModel CreateViewModel() { 
     var vm = _factory.CreateViewModel(); 
     vm.User = new User(); 
     return vm; 
    } 
} 

et deux spécifiques pour le contrôleur:

public class HomeV1ViewModelFactory : IHomeViewModelFactory { 
    public HomeViewModel CreateViewModel() { 
     // logic only for V1 to create vm 
     var vm = new HomeViewModel { 
      Articles = new Articles() 
     }; 
     return vm; 
    } 
} 

public class HomeV2ViewModelFactory: IHomeViewModelFactory { 
    public HomeViewModel CreateViewModel() { 
     // logic only for V2 to create vm 
     var vm = new HomeViewModel { 
      Issues = new Issues() 
     }; 
     return vm; 
    } 
} 

maintenant les HomeV1Controller doit avoir injecté UserViewModelFactory qui a la dépendance de HomeV1ViewModelFactory et HomeV2Controller doit avoir injecté UserViewModelFactory qui a la dépendance de HomeV2ViewModelFactory.

+0

En règle générale, nous ne mettons pas la logique métier dans ViewModels et donc il n'y a aucune raison de se moquer ou de revenir au conteneur de DI à créez-les. L'utilisation du mot clé 'new' suffira. Voir [cet article de blog] (https://cuttingedge.it/blogs/steven/pivot/entry.php?id=97) pour plus de détails. – NightOwl888

+0

@ NightOwl888 Je ne mets aucune logique pour voir le modèle lui-même. Mais la logique veut que vm soit créé. – mardok

+0

C'est bon. Mon point est qu'il n'y a aucune raison d'utiliser une usine ou un conteneur DI pour créer vos modèles de vue. Vous n'avez pas besoin d'abstraction dans ce scénario. Le code que vous avez a l'air bien (à l'exception du paramètre de constructeur inutile IHomeViewModelFactory). – NightOwl888

Répondre

1

La seule chose que je peux penser est prioritaire de service:

 container.Register(Component.For<HomeV1Controller>() 
      .DependsOn(Property.ForKey<IHomeViewModelFactory>().Is("UserViewModelFactory1"))); 
     container.Register(Component.For<HomeV2Controller>() 
      .DependsOn(Property.ForKey<IHomeViewModelFactory>().Is("UserViewModelFactory2"))); 

     container.Register(Component.For<IHomeViewModelFactory>() 
      .ImplementedBy<UserViewModelFactory>() 
      .Named("UserViewModelFactory1") 
      .DependsOn(Property.ForKey<IHomeViewModelFactory>().Is("HomeV1ViewModelFactory"))); 

     container.Register(Component.For<IHomeViewModelFactory>() 
      .ImplementedBy<UserViewModelFactory>() 
      .Named("UserViewModelFactory2") 
      .DependsOn(Property.ForKey<IHomeViewModelFactory>().Is("HomeV2ViewModelFactory"))); 

     container.Register(Component.For<IHomeViewModelFactory>().ImplementedBy<HomeV1ViewModelFactory>().Named("HomeV1ViewModelFactory")); 
     container.Register(Component.For<IHomeViewModelFactory>().ImplementedBy<HomeV2ViewModelFactory>().Named("HomeV2ViewModelFactory"));