1. #1
    Expert confirmé
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    février 2010
    Messages
    3 054
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : février 2010
    Messages : 3 054
    Points : 5 006
    Points
    5 006
    Billets dans le blog
    1

    Par défaut Charger des dépendances uniquement quand on en a besoin

    Bonjour,

    Je travaille sur un programme d'extraction/transformation de données.

    En se basant sur une variable (qui, si possible, peut évoluer au fil de l'exécution du programme), je détermine quel connecteur de base de données utiliser :
    - Natif SQL Server
    - ODBC
    - OLE BD
    (et pourquoi pas MySQL, Oracle, DB2, etc.)

    Voici une partie du code concernée :
    Code csharp : 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
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
     
    using System.Data;
    using System.Data.SqlClient;
    using System.Data.Odbc;
    using System.Data.OleDb;
     
    [...]
            public IDbConnection Cnx
            {
                get
                {
                    if (_Cnx == null)
                    {
                        switch (CnxType)
                        {
                            case "mssql":
                                _Cnx = new SqlConnection(CnxString);
                                break;
                            case "oledb":
                                _Cnx = new OleDbConnection(CnxString);
                                break;
                            case "odbc":
                                _Cnx = new OdbcConnection(CnxString);
                                break;
                            default:
                                throw new NotImplementedException(CnxType);
                        }
                    }
                    if (_Cnx.State != ConnectionState.Open)
                    {
                        _Cnx.Open();
                    }
                    return _Cnx;
                }
            }
    [...]

    L'avantage de ce code, c'est qu'ici, je crée mon objet de connexion à la base de données en fonction du type de base désirée, et travaillant par la suite avec un IDbConnection, je ne suis pas obligé de dupliquer tout mon code pour travailler.

    En contre-partie, je me retrouve avec plein de "using" inutiles.
    Et obligé d'installer sur le PC cible tous les connecteurs prévus, même ceux qui ne servent à rien dans le contexte d'utilisation.

    Est-ce possible de faire le "using" au moment de l'exécution, plutôt qu'au moment de la compilation ? (et éventuellement planter lamentablement si le connecteur n'est pas présente)
    On ne jouit bien que de ce qu’on partage.

  2. #2
    Expert confirmé

    Homme Profil pro
    Chef de projet NTIC
    Inscrit en
    septembre 2006
    Messages
    3 575
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Chef de projet NTIC
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : septembre 2006
    Messages : 3 575
    Points : 5 173
    Points
    5 173

    Par défaut

    Salut

    tu devrais jeter un oeil du coté de MEF (Managed Extension Framework)

    L'idée sera alors de monter la dll dynamiquement et d'instancier (Activator.CreateInstance de mémoire) directement un objet de ta dll qui implémentera l'interface
    que tu attends...

    Comme ça, tu devrais pouvoir te passer de tout binder à la génération du projet.
    The Monz, Toulouse
    Expertise dans la logistique et le développement pour
    plateforme .Net (Windows, Windows CE, Android)

  3. #3
    Expert confirmé
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    février 2010
    Messages
    3 054
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : février 2010
    Messages : 3 054
    Points : 5 006
    Points
    5 006
    Billets dans le blog
    1

    Par défaut

    Si j'ai bien compris, je dois créer 1 DLL pour chaque type de connexion (ou tout du moins une classe par type de connexion, dans 1 ou plusieurs DLL) qui référence chaque drivers SQL.
    Et en fonction du contexte, je déploie l'application avec telle ou telle DLL ?

    Mmmmm... Je vais étudier la question...
    On ne jouit bien que de ce qu’on partage.

  4. #4
    Modérateur
    Avatar de DotNetMatt
    Homme Profil pro
    CTO
    Inscrit en
    février 2010
    Messages
    3 352
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 29
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : CTO
    Secteur : Finance

    Informations forums :
    Inscription : février 2010
    Messages : 3 352
    Points : 8 862
    Points
    8 862
    Billets dans le blog
    3

    Par défaut

    Les references sont chargees en memoire a la volee, lorsqu'elles sont necessaires. C'est-a-dire lorsqu'on rentre dans une methode, la CLR va verifier si les assemblies requis sont deja charges ou pas, et les charger le cas echeant.

    Donc si ton architecture est bien decoupee, et tes modules bien isoles les uns des autres, alors tu peux faire tourner ton application meme s'il manque des references. Lorsque tu appeleras une methode qui necessite une reference manquante, cela va declencher l'exception suivante :
    Unhandled Exception: System.IO.FileNotFoundException: Could not load file or assembly 'xxxx, Version=y.y.y.y, Culture=neutral, PublicKeyToken=00aa0aa0a0a0aaaa' or one of its dependencies. The system cannot find the file specified.
    Un peu de lecture pour la route :
    - Back to Basics: When does a .NET Assembly Dependency get loaded
    - The CLR Loader

    Sinon, en cas de problemes de conception la solution de theMonz31 fonctionnera aussi tres bien, mais ca nessite du developpement.
    Less Is More
    Pensez à utiliser les boutons , et les balises code
    Desole pour l'absence d'accents, clavier US oblige

  5. #5
    Expert confirmé
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    février 2010
    Messages
    3 054
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : février 2010
    Messages : 3 054
    Points : 5 006
    Points
    5 006
    Billets dans le blog
    1

    Par défaut

    Euh...

    Donc dans mon cas, si CnxType est toujours égal à "mssql", alors les DLL contenant les classes OleDbConnection et OdbcConnection peuvent être absentes, ça marchera quand même ???
    On ne jouit bien que de ce qu’on partage.

  6. #6
    Modérateur
    Avatar de DotNetMatt
    Homme Profil pro
    CTO
    Inscrit en
    février 2010
    Messages
    3 352
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 29
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : CTO
    Secteur : Finance

    Informations forums :
    Inscription : février 2010
    Messages : 3 352
    Points : 8 862
    Points
    8 862
    Billets dans le blog
    3

    Par défaut

    Les 2 classes que tu cites sont dans la meme DLL : System.Data.dll. Si on prend le provider MySQMerde par exemple, voici un cas concret :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    public static void Main(string[] args)
    {
         var prog = new Program();
     
        prog.NoDependency();
        prog.WithDependency();
     
        Console.ReadKey();
    }
    Le code qui marche sans dependence particuliere :
    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
    private void NoDependency()
    {
    	try
    	{
    		// Ici tu peux faire tout ce que tu veux, tant que tu n'appelles pas de code faisant reference a MySql.Data.dll.
    		var i = 1 + 1;
     
    		Console.WriteLine("Appel de NoDependency() sans exception levee");
    	}
    	catch (Exception ex)
    	{
    		// On n'atteindra jamais cette ligne
    		Console.WriteLine(string.Format("Appel de NoDependency() avec une exception: {0}", ex.Message));
    	}
    }
    Le code qui fait appel a la dependence MySql.Data.dll :
    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
    private void WithDependency()
    {
    	try
    	{
    		// Cette ligne va lancer une exception si tu as deploye sans la DLL MySql.Data.dll.
    		var conn = new MySqlConnection();
     
    		// On n'atteindra jamais cette ligne, tant que la DLL ne sera pas presente
    		Console.WriteLine("Appel de WithDependency() sans exception levee");
    	}
    	catch (Exception ex)
    	{
    		Console.WriteLine(string.Format("Appel de WithDependency() avec une exception: {0}", ex.Message));
    	}
    }
    Pour que ca compile, il faut rajouter une reference au package MySql.Data.

    Ensuite lors du deploiement, si tu deploies MySql.Data.dll avec ton projet, la methode WithDependency() s'executera normalement et ne levera pas d'exception.
    Si tu ne deploies pas MySql.Data.dll, la methode WithDependency() levera une exception.

    Quoiqu'il arrive, la methode NoDependency() s'executera normalement.
    Less Is More
    Pensez à utiliser les boutons , et les balises code
    Desole pour l'absence d'accents, clavier US oblige

  7. #7
    Expert confirmé
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    février 2010
    Messages
    3 054
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : février 2010
    Messages : 3 054
    Points : 5 006
    Points
    5 006
    Billets dans le blog
    1

    Par défaut

    Ok merci !

    Donc à priori (sauf si mon code actuel ne le permet pas, auquel cas je le modifierai) ce que j'ai fais fonctionnera comme désiré tout seul.

    J'étais persuadé que .NET vérifiait toutes les dépendances au démarrage.
    J'ai trop fais de Visual Basic 6 à mes débuts je crois
    On ne jouit bien que de ce qu’on partage.

  8. #8
    Rédacteur/Modérateur

    Avatar de François DORIN
    Homme Profil pro
    Consultant informatique
    Inscrit en
    juillet 2016
    Messages
    1 416
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : juillet 2016
    Messages : 1 416
    Points : 4 774
    Points
    4 774
    Billets dans le blog
    5

    Par défaut

    Bonjour,

    Citation Envoyé par StringBuilder Voir le message
    J'étais persuadé que .NET vérifiait toutes les dépendances au démarrage.
    Il me semble pourtant que c'est le cas. Pour les assembly qui apparaissent en tant que référence et qui sont effectivement utilisées, le chargement se fait au démarrage.
    Si un assembly est référencé mais n'est pas utilisé statiquement, il n'est pas chargé. Mais il le sera automatiquement si l'assembly est accédée d'une manière ou d'une autre, via la réflexivité.
    François DORIN
    Consultant informatique : conception, modélisation, développement (C#/.Net et SQL Server)
    Site internet | Profils Viadéo & LinkedIn
    ---------
    Page de cours : fdorin.developpez.com
    ---------
    N'oubliez pas de consulter la FAQ C# ainsi que les cours et tutoriels

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Charger des fichiers d'un repertoire
    Par demanghonj dans le forum IO
    Réponses: 4
    Dernier message: 05/01/2005, 18h23
  2. [Dexplore] Comment charger des fichiers d'aide ?
    Par Laurent Dardenne dans le forum Windows
    Réponses: 5
    Dernier message: 04/01/2005, 18h38
  3. Charger des paramètres à partir de beans
    Par lalakers dans le forum ANT
    Réponses: 1
    Dernier message: 19/05/2004, 19h25
  4. Recherche des dépendances des modules
    Par slowpoke dans le forum Mandriva / Mageia
    Réponses: 9
    Dernier message: 11/12/2003, 09h49

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