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 :

Bataille avec le Unity et la règle CA2000


Sujet :

C#

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Expert confirmé
    Avatar de popo
    Homme Profil pro
    Analyste programmeur Delphi / C#
    Inscrit en
    Mars 2005
    Messages
    3 010
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Analyste programmeur Delphi / C#
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2005
    Messages : 3 010
    Par défaut Bataille avec le Unity et la règle CA2000
    Bonjour,

    Je dois reprendre un projet avec Unity car mon manager veut que je corrige tous les avertissement remonté par l'analyseur de code.

    A l'origine il y a ce bout de code qui provoque l'avertissement CA2000.
    - Il s'agit d'une méthode static dans une classe static (si ça peut aider)
    - Container est également est de type UnityContainer
    - new HierarchicalLifetimeManager() déclenche l'avertissement
    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Container.RegisterType<ICustomRepository<Customer>, CustomRepository<Customer>>(new HierarchicalLifetimeManager());
    Container.RegisterType<ICustomRepository<Provider>, CustomRepository<Provider>>(new HierarchicalLifetimeManager());
    // Encore une dizaine de lignes sur le même moule

    En cherchant un peu sur le net, j'ai découvert un POST de 2010 sur StackOverFlow (réponse qui a été validée et qui est donc normalement bonne) :
    https://stackoverflow.com/questions/...rcontrolledlif

    J'ai donc adapté mon code en créant la méthode suivante :
    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    private static void RegisterType<TFrom, TTo>() where TTo : TFrom
    {
        var manager = new HierarchicalLifetimeManager();
        try
        {
            Container.RegisterType<TFrom, TTo>(manager);
        }
        catch
        {
            manager.Dispose();
            throw;
        }
    }

    Et en l'appelant de la manière suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    RegisterType<ICustomRepository<Customer>, CustomRepository<Customer>>();
    Au lieu d'avoir plusieurs avertissement CA2000, j'en ai plus qu'un sur ma nouvelle méthode mais toujours sur le new HierarchicalLifetimeManager

    Quelqu'un a-t-il une idée pour corriger cet avertissement ?
    Merci.

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

    Informations professionnelles :
    Activité : edi

    Informations forums :
    Inscription : Juin 2007
    Messages : 941
    Par défaut
    Est-ce-que ça change quelque chose si tu déplaces l'appel au constructeur dans le try ?

  3. #3
    Expert confirmé
    Avatar de popo
    Homme Profil pro
    Analyste programmeur Delphi / C#
    Inscrit en
    Mars 2005
    Messages
    3 010
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Analyste programmeur Delphi / C#
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2005
    Messages : 3 010
    Par défaut
    J'avais déjà essayé de la manière suivante mais ça n'a rien changé :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    private static void RegisterType<TFrom, TTo>() where TTo : TFrom
    {
        HierarchicalLifetimeManager manager = null;
        try
        {
            manager = new HierarchicalLifetimeManager();
            Container.RegisterType<TFrom, TTo>(manager);
        }
        catch
        {
            manager.Dispose();
            throw;
        }
    }

  4. #4
    Expert confirmé

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

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

    Informations forums :
    Inscription : Juillet 2016
    Messages : 2 761
    Billets dans le blog
    21
    Par défaut
    Une première possibilité serait de préciser explicitement d'ignorer l'avertissement en décorant la méthode avec un attribut
    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    [SuppressMessage("Microsoft.Reliability",
                     "CA2000:DisposeObjectsBeforeLosingScope",
                     Justification = "Propriété transférée à Container")]
    .

    Sinon, peut être (je n'ai pas restesté) une seconde possibilité c'est de créer une méthode qui s'occupe d'instancier l'instance et la retourne. Donc simplement :
    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    private static HierarchicalLifetimeManager CreateManager()
    {
       return new HierarchicalLifetimeManager();
    }
    car il me semble que l'avertissement CA2000 n'est généré que dans la méthode où l'objet est créé. Donc en déportant la création dans un autre objet, l'avertissement devrait disparaître.

  5. #5
    Membre expérimenté
    Homme Profil pro
    Analyste Programmeur
    Inscrit en
    Septembre 2008
    Messages
    176
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Analyste Programmeur
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 176
    Par défaut
    Bonjour,

    Cet avertissement survient car tu instancie un objet (HierarchicalLifetimeManager) dans ta méthode qui n'est potentiellement jamais disposé (sauf en passant le catch).
    - Une solution pourrait être d'instancier ton objet non pas dans la méthode, mais dans la classe (dans le constructeur par exemple) et de le disposer dans le destructeur de la classe (si c'est possible suivant le contexte).
    - Je ne connais pas spécialement bien Unity, mais j'ai quand même trouvé ceci : https://docs.microsoft.com/en-us/pre...82(v=pandp.20) qui devrait te permettre de laisser le container faire l'instanciation de l'objet que tu veux passer en paramètre (InjectionConstructor). Ça devrait devrait corriger ton avertissement, car ce n'est plus toi qui fait le new. A tester.

    Donc en déportant la création dans un autre objet, l'avertissement devrait disparaître.
    C'est vrai, mais ça risque aussi de déporter l'avertissement si ce n'est pas l'objet qui fait la création, qui fait le dispose.

    Bonne continuation.

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

    Informations professionnelles :
    Activité : CTO
    Secteur : Finance

    Informations forums :
    Inscription : Février 2010
    Messages : 3 611
    Billets dans le blog
    3
    Par défaut
    Ca donne quoi avec un finally ?
    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    try
    {
        // …
    }
    catch
    {
        throw;
    }
    finally
    {
        manager.Dispose();
    }
    Comme cela on s'assure que manager est toujours dispose, exception ou pas exception.
    Less Is More
    Pensez à utiliser les boutons , et les balises code
    Desole pour l'absence d'accents, clavier US oblige
    Celui qui pense qu'un professionnel coute cher n'a aucune idee de ce que peut lui couter un incompetent.

  7. #7
    Expert confirmé
    Avatar de popo
    Homme Profil pro
    Analyste programmeur Delphi / C#
    Inscrit en
    Mars 2005
    Messages
    3 010
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Analyste programmeur Delphi / C#
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2005
    Messages : 3 010
    Par défaut
    Citation Envoyé par François DORIN Voir le message
    Une première possibilité serait de préciser explicitement d'ignorer l'avertissement en décorant la méthode avec un attribut
    Sinon, peut être (je n'ai pas restesté) une seconde possibilité c'est de créer une méthode qui s'occupe d'instancier l'instance et la retourne. Donc simplement :
    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    private static HierarchicalLifetimeManager CreateManager()
    {
       return new HierarchicalLifetimeManager();
    }
    car il me semble que l'avertissement CA2000 n'est généré que dans la méthode où l'objet est créé. Donc en déportant la création dans un autre objet, l'avertissement devrait disparaître.
    ça ne me génère plus d'avertissement sur le new de cette manière.
    Mais l'appel à CreateManager me déclenche le même avertissement.
    Dommage.

    Citation Envoyé par Noxen Voir le message
    IL y a un e-book de référence concernant Unity :
    Microsoft Pattern & Practice : Unity Container

    Dans les exemples de code proposés concernant le HierarchicalLifetimeManager tous font l'instanciation directement "inline" dans l'appel de fonction, ils n'utilisent pas de structure try/catch. J'aurais tendance à penser que cette structure n'est pas nécessaire en l'occurrence, une erreur ne pourrait se produire que dans le constructeur du HierarchicalLifetimeManager, cas qui me paraît improbable, ou dans la méthode Resolve, qui prend peut-être déjà en charge le Dispose. Quand à savoir si ça jouerai sur le rapport de warning je n'en ai aucune idée.
    Citation Envoyé par François DORIN Voir le message
    Une première possibilité serait de préciser explicitement d'ignorer l'avertissement en décorant la méthode avec un attribut
    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    [SuppressMessage("Microsoft.Reliability",
                     "CA2000:DisposeObjectsBeforeLosingScope",
                     Justification = "Propriété transférée à Container")]
    .
    ça ma poussé à regarder ce que UnityContainer faisait de cet objet et j'ai découvert ceci :
    Dans la méthode RegisterType
    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    if (registration.LifetimeManager is IDisposable manager)
        container._lifetimeContainer.Add(manager);

    Dans le Dipose de UnityContainer
    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    _lifetimeContainer.Dispose();

    Dans le dispose de LifetimeContainer
    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    foreach (var disposable in disposables)
    {
        try
        {
            disposable.Dispose();
        }
            catch (Exception e)
        {
            exceptions.Add(e);
        }
    }

    Dans la mesure où le container s'occupe d'appeler le Dispose, je vais simplement ignorer l'avertissement.
    Merci à vous deux.

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

Discussions similaires

  1. Réponses: 5
    Dernier message: 02/06/2016, 09h12
  2. envoyer un email avec plc UNITY et ETY4103
    Par abyss68 dans le forum Automation
    Réponses: 1
    Dernier message: 15/06/2015, 15h46
  3. Réponses: 0
    Dernier message: 05/02/2014, 00h33
  4. Bataille avec le ruban d'Outlook
    Par popo dans le forum C#
    Réponses: 1
    Dernier message: 20/12/2012, 16h55
  5. Bataille avec \ref et \pageref
    Par Pharmacos dans le forum Mise en forme
    Réponses: 3
    Dernier message: 02/06/2009, 18h55

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