IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C# Discussion :

Framework perso et injection de dépendance (ou pas)


Sujet :

C#

  1. #1
    Membre habitué Avatar de Nadinette
    Femme Profil pro
    Développeur Web
    Inscrit en
    Octobre 2012
    Messages
    264
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2012
    Messages : 264
    Points : 144
    Points
    144
    Par défaut Framework perso et injection de dépendance (ou pas)
    Bonjour,

    Ca fait un certain temps que je me fabrique des petits helpers et des classes de base en C#.
    Aujourd'hui, on voit beaucoup d'injection de dépendance et il y a un truc qui m'échappe.

    Admettons que je crée une classe de base MonControlleur qui hérite de la classe Controlleur qui fait partie d'une dll Microsoft (en vrai c'est du mvc).

    J'ai peut-être mal compris l'injection de dépendance et je me demandais si ça se fait ou si c'est recommandé de le faire, d'injecter la dll du framework dans le projet.
    Si oui, est-il ensuite possible de faire hériter un controlleur du projet mvc de MonControlleur ?

    Peut-être est il souhaitable de passer par l'interface du style

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    class HomeControlleur : IMoncontrolleur{
         HomeControlleur (IMoncontrolleur monControlleur){
     
        }
    }
    C'est pas bien clair dans ma tête. Vous pourriez m'expliquer ?

    Merci

  2. #2
    Membre chevronné
    Homme Profil pro
    edi
    Inscrit en
    Juin 2007
    Messages
    899
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : edi

    Informations forums :
    Inscription : Juin 2007
    Messages : 899
    Points : 1 916
    Points
    1 916
    Par défaut
    Bonjour, je vais tenter d'éclaircir un peu les choses.

    Un module utilise / est composé de différents autres modules dont, du coup, il dépend, notamment lorsque ces modules sont instanciés en son sein. L'injection de dépendance consiste de façon générale à externaliser la gestion de ces modules et à les insérer (injecter) dans le module client afin de diminuer la dépendance. On en parle plus souvent dans la composition de classes, bien cela puisse concerner par exemple informations de configuration ou des dll (une architecture de plugins constitue un exemple d'injection de dépendance puisque les fonctionnalités apportées par les plugins sont définies à l'extérieur de l'application elle-même et insérée au démarrage ou à la volée). Pour une classe l'injection peut se faire via différents points d'entrée : un constructeur, un méthode de set, une propriété public, l'utilisation d'une classe avec un singleton ou des méthodes statiques initialisées à l'extérieur...

    Prenons le cas d'une application web qui analyse un fichier de données et retourne des statistiques. On a un AnalysisController qui utilise un AnalysisService :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    public class AnalysisController : Controller
    {
        public AnalysisController()
        {
            _service = new AnalysisService();
        }
    }
    Dans le cas présent on ne peut pas faire grand chose avec le service d'analyse et il n'est par exemple très compliqué de faire des tests unitaires dessus. En prenant un peu de recul et en utilisant une interface on peut définir un constructeur prenant un service en paramètre et un autre créant un service par défaut pour que le contrôleur reste compatible avec le contexte ASP MVC :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    public class AnalysisController : Controller
        {
            public AnalysisController() : this(new AnalysisService()) { }
     
            public AnalysisController(IAnalysisService service)
            {
                _service = service;
            }
     
            private IAnalysisService _service;
     
        }
    Il devient maintenant possible dans un test unitaire d'instancier unitairement un AnalysisController et de lui donner en paramètre une contre-façon de IAnalysisService. Allons un peu plus loin, on pourrait créer un classe qui stocker les dépendances et les fournit à la demande :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    public interface IDependencyManager
        {
            object Get(object key);
            T Get<T>() where T : class;
            void Set(object key, object obj);
            void Set<T>(T obj) where T : class;
        }
     
        public class DependencyManager : IDependencyManager
        {
            public static DependencyManager Instance { get; } = new DependencyManager();
     
            private readonly Dictionary<object, object> _container = new Dictionary<object, object>();
     
            public object Get(object key) { return _container[key]; }
            public T Get<T>() where T : class { return Get(typeof(T)) as T; }
            public void Set(object key, object obj) { _container[key] = obj; }
            public void Set<T>(T obj) where T : class { Set(typeof(T), obj); }
        }
    On peut enregistrer les dépendances dans la méthode Application_Start située dans le ficheir Global.asax.cs à côté des autres initialisations :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    protected void Application_Start()
            {
                var manager = DependencyManager.Instance;
                var service = new AnalysisService();
                // service enregistré sous son type propre
                manager.Set(service);
                // service enregistré sous le type de l'interface
                manager.Set<IAnalysisService>(service);
            }
    Il est ainsi possible de spécifier au démarrage de l'application, dans cette méthode ou via un fichier de configuration, les instances à utiliser au cours de l'exécution. On peut ensuite modifier le contrôleur de cette façon afin d'utiliser un service déterminer dynamiquement :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    public class AnalysisController : Controller
        {
            public AnalysisController() : this(DependencyManager.Instance) { }
     
            public AnalysisController(DependencyManager manager) : this(manager.Get<IAnalysisService>() ?? new AnalysisService()) { }
     
            public AnalysisController(IAnalysisService service)
            {
                _service = service;
            }
     
            private IAnalysisService _service;
        }
    Il existe des framework prenant en charge l'injection de dépendance comme Spring.net (portage du Spring de Java), Unity (à ne pas confondre avec le moteur de jeu du même nom) ou MEF (Managed Extensibility Framework). ASP MVC quand à lui propose une implémentation légère s'appuyant sur l'interface IDependancyResolver et la classe DependancyResolver que tu peux trouver sur la MSDN : DependancyResolver.

    J'espère que cette présentation sommaire te permettra de mieux comprendre la notion d'injection de dépendance. N'hésite pas à poser des questions si tu as besoin de précisions. Bon courage à toi !

  3. #3
    Membre habitué Avatar de Nadinette
    Femme Profil pro
    Développeur Web
    Inscrit en
    Octobre 2012
    Messages
    264
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2012
    Messages : 264
    Points : 144
    Points
    144
    Par défaut
    Merci pour ces explications très claires.

    Dans le cas de MVC. On défini des ViewModels qui permettent d'alimenter les vues.
    Est-il possible d'injecter une dll dans un projet ASP.net MVC et qu'ensuite, le ViewModel puisse hériter (proprement d'une classe de base abstraite incluse dans la dll injectée) ?
    J'ai l'impression qu'avec les dll injectées, on ne peut hériter que des interfaces.
    Dans ma tête, ça n'est pas possible pour les classes de base mais j'aimerai avoir confirmation.

    Merci

  4. #4
    Membre chevronné
    Homme Profil pro
    edi
    Inscrit en
    Juin 2007
    Messages
    899
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : edi

    Informations forums :
    Inscription : Juin 2007
    Messages : 899
    Points : 1 916
    Points
    1 916
    Par défaut
    Tout d'abord on ne parle pas d'injecter une dll dans un projet (pas dans ce contexte en tout cas) ; par contre on peut la référencer. Si tes deux projets sont dans la même solution il suffit d'ajouter une référence au projet à importer ; l'utilitaire Nuget permet de gérer les dépendances sur des bibliothèques externes ; il est enfin possible de référencer une dll locale, sur ton système de fichier (pas recommandé pour les gestion de projet et le travail collaboratif).

    Les éléments d'un assembly on une accessibilité, c'est-à-dire un visibilité, qui définit qui peut utiliser l'élément en question :
    - public : accessible à tous, même depuis l'extérieur de l'assembly ;
    - protected : accessible aux types dérivés (internes ou externes) ;
    - internal : seulement à l'intérieur de l'assembly ;
    - internal protected : accessible aux types dérivés et aux éléments du même assembly ;
    - private : uniquement à l'intérieur de l'élément.

    Si un élément (class, struc, propeprty, enum...) est déclaré en accès public, il sera disponible pour tout utilisateur. Par exemple tes classes de contrôleurs doivent hériter de System.Web.Mvc.Controller, définie dans l'assembly System.Web.Mvc.dll. Tu peux te créer un type de base dans une dll que tu vas référencer dans ton projet et dériver dans ton projet ASP MVC :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    namespace MaDll
    {
        public abstract class ControllerBase : Controller
        {
            protected ControllerBase(IDependencyResolver resolver = null)
            {
                if(resolver != null) Resolver = resolver;
            }
        }
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    namespace MonProjetAspMvc.Controllers
    {
        public class DerivedController : ControllerBase
        {
            public DerivedController() : this(null) { }
            public DerivedController(IDependencyResolver resolver) : base(resolver) { }
        }
    }
    Par contre tu semble avoir l'idée d'utiliser une classe de base pour les modèles des vues, mais je ne pense pas que ce soit une bonne idée. Il faut considérer ces modèles comme de simple "passe-plat", qui vont transmettre les données de la requête http à l'action puis de l'action à la vue. Ces informations sont vraiment spécifiques à un contexte et ne requièrent en soit que très peu de comportement, aussi il ne me parait pas pertinent d'avoir une classe de base pour ces objets. Et puis, que mettrais-tu en commun entre tous ces objets ?

Discussions similaires

  1. Réponses: 2
    Dernier message: 10/09/2010, 14h35
  2. Réponses: 4
    Dernier message: 30/09/2009, 22h41
  3. [EJB3] Injection de dépendance et Stateful
    Par newbeewan dans le forum Java EE
    Réponses: 1
    Dernier message: 15/05/2007, 07h33
  4. [Integration] [EasyMock] Injection de dépendance à l'éxécution
    Par frangin2003 dans le forum Spring
    Réponses: 2
    Dernier message: 06/03/2007, 11h06
  5. Spring + TagSupport et injection de dépendance
    Par worldchampion57 dans le forum Spring Web
    Réponses: 2
    Dernier message: 26/02/2007, 09h01

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo