Forum Programmation.c# Custom attributes: le retour :-(

Posté par  .
Étiquettes : aucune
0
12
fév.
2005
Bonjour,
désolé de poster un nouveau message à propos des custom attributes. Les exemples que j'ai pu trouvés sur internet ne m'ont pas permis de comprendre ce qui ne va pas dans mon code

Dans une dll:
[assembly:AssemblyDependencies( "ee","1.0.0.0","aa", "1.0.0.0")]

le custom atttribute est défini ainsi::
[AttributeUsage(AttributeTargets.Assembly)]
public class AssemblyDependencies : Attribute
{
public Hashtable Dependencies;

public AssemblyDependencies(params string[] dependencies)
{
Dependencies = new Hashtable();

if (dependencies.Length % 2 == 0)
{
for(int count = 0; count < dependencies.Length; count += 2)
{
try
{
this.Dependencies.Add(dependencies[count], new Version(dependencies[count+1]));
}
catch(Exception e)
{
Console.WriteLine("Error");
}
}
}
}
}


Dans un autre programme, je charge la dll:
Assembly asm = Assembly.LoadFrom(this.fullName);

Attribute[] attributes;
try
{
attributes = Attribute.GetCustomAttributes(asm);
}
catch(Exception e)
{
Console.WriteLine("Error");
}

foreach(Attribute attribute in attributes)
{
AssemblyDependencies dependencies = attribute as AssemblyDependencies;

if (dependencies != null)
{
try
{
Console.WriteLine("{0}", dependencies.Dependencies);
}
catch(Exception e)
{
Console.WriteLine("Error");
}
}
else
Console.WriteLine("{0} is null", attribute);
}
}

Prblème: j'ai "AssemblyDependencies is null"!

Pourtant, quand je fais exactement la même chose pour System.Reflection.AssemblyTitleAttribute, cela marche correctement

Le chemin de la dll est correct, et les dependences sont correctement ajoutées dans AssemblyDependencies

Qu'est-ce qui ne va pas dans ce bout de code?

Merci
  • # monodis

    Posté par  . Évalué à 1.

    Voilà ce que me donne la commande "monodis Plugin.dll":

    .assembly extern mscorlib
    {
    .ver 1:0:5000:0
    }
    .assembly 'Plugin'
    {
    .custom instance void class [mscorlib]System.Reflection.AssemblyTitleAttribute::.ctor(string) = (
    01 00 18 4A 75 6C 69 65 6E 53 6F 62 72 69 65 72 // ...JulienSobrier
    46 69 72 73 74 50 6C 75 67 69 6E 00 00 ) // FirstPlugin..

    .custom instance void class AssemblyEventsTrigger::.ctor(string[]) = (
    01 00 02 00 00 00 07 6F 6E 53 74 61 72 74 06 6F // .......onStart.o
    6E 53 74 6F 70 00 00 ) // nStop..

    .custom instance void class AssemblyDependencies::.ctor(string[]) = (
    01 00 04 00 00 00 02 65 65 07 31 2E 30 2E 30 2E // .......ee.1.0.0.
    30 02 61 61 07 31 2E 30 2E 30 2E 30 00 00 ) // 0.aa.1.0.0.0..

    .hash algorithm 0x00008004
    .ver 0:1:1:1
    }
    [...]
  • # chezmoicamarche.org

    Posté par  (site web personnel) . Évalué à 3.

    Effectivement tu n'as pas bien compris le schmurck :)
    Premièrement c'est normale le is null, tu fais ton test dans une boucle foreach, et tu peux très bien trouvé tout pleins d'autres attributes uqi ne sont pas les tiens.

    En tout cas chez moi j'ai essayé ton attribute dans une dll, et j'ai testé avec ca :
    Assembly asm = Assembly.LoadFrom("plugin.dll");
    Attribute[] attributes = Attribute.GetCustomAttributes(asm);

    foreach(Attribute attribute in attributes)
    {
    if (attribute is AssemblyDependencies)
    {
    Console.WriteLine("trouvé !");
    AssemblyDependencies ds = (AssemblyDependencies)attribute;
    foreach(string s in ds.Dependencies.Keys) Console.WriteLine(s+" : "+ds.Dependencies[s]);
    }
    }

    et ma fois ca marche nickel, j'obtiens ca en résultat :
    trouvé !
    aa : 1.0.0.0
    ee : 1.0.0.0

    Sinon plutôt que de faire un attribute avec un nombre variable d'argument, tu peux aussi en mettre que 2, nom+version, et proposer à l'utilisateur de mettre plusieurs fois l'attribut s'il veut multiplié les dependances.

    Ah oui aussi je sais pas trop ce que tu veux faire, mais la gestion des dépendances d'habitudes c'est un obulot réservé au CLR, et tu n'as absolument rien à faire pour les gérer mais bon :)
    • [^] # Re: chezmoicamarche.org

      Posté par  . Évalué à 1.


      Effectivement tu n'as pas bien compris le schmurck :)
      Premièrement c'est normale le is null, tu fais ton test dans une boucle foreach, et tu peux très bien trouvé tout pleins d'autres attributes uqi ne sont pas les tiens.

      Je sais, le probleme est que AssemblyDependencies est egalement null.


      En tout cas chez moi j'ai essayé ton attribute dans une dll, et j'ai testé avec ca :
      Assembly asm = Assembly.LoadFrom("plugin.dll");
      Attribute[] attributes = Attribute.GetCustomAttributes(asm);

      foreach(Attribute attribute in attributes)
      {
      if (attribute is AssemblyDependencies)
      {
      Console.WriteLine("trouvé !");
      AssemblyDependencies ds = (AssemblyDependencies)attribute;
      foreach(string s in ds.Dependencies.Keys) Console.WriteLine(s+" : "+ds.Dependencies[s]);
      }
      }

      et ma fois ca marche nickel, j'obtiens ca en résultat :
      trouvé !
      aa : 1.0.0.0
      ee : 1.0.0.0

      Merci beaucoup d'avoir teste. mais chez moi, ca ne marche toujours pas avec le code que tu as donne!
      Faut-il compiler le plugin avec certaines otpions? J'ai juste fait "mcs -target:library Plugin.cs ../PluginInterface.cs ../Session.cs"Faut-il utiliser


      Sinon plutôt que de faire un attribute avec un nombre variable d'argument, tu peux aussi en mettre que 2, nom+version, et proposer à l'utilisateur de mettre plusieurs fois l'attribut s'il veut multiplié les dependances.

      C'est note


      Ah oui aussi je sais pas trop ce que tu veux faire, mais la gestion des dépendances d'habitudes c'est un obulot réservé au CLR, et tu n'as absolument rien à faire pour les gérer mais bon :)

      CLR?
      • [^] # Re: chezmoicamarche.org

        Posté par  . Évalué à 1.

        J'ai oublie de preciser que cela marche par contre tres bien auand j'essaye d'obtenir l'information a l'interieur de Plugin.dll
      • [^] # Re: chezmoicamarche.org

        Posté par  (site web personnel) . Évalué à 2.

        mmmh je crois savoir d'où vient ton problème.

        Visiblement tu compiles ton plugin avec le source de l'attribute, puis tu recompiles le programme qui cherche les plugins avec ce même source... je me trompes ?
        Donc du coup chacun a sa version de la définition, et malgrès le partage de source, le CLR (Common Langage Runtime, autrement dit l'environnement d'exécution, plus comunément appelé machine virtuelle, qui se lance avec la commande mono) voit 2 versions différentes (ils ont chacuns un numéro de version, etc.)

        Ce qu'il faut faire dans ton cas précis :

        compiler dans une dll tout ce qui doit être "partagé", autrement dit ce qui doit être connu des plugins et du gestionnaire de plugin, cad en gros les def d'attributes, les interfaces, les classes manipulables par les plugins, etc.
        mcs -

        ensuite tu compiles un plugin comme ceci :
        mcs -target:library monPlugin.cs -r:MonAppliQuiContientLesDefs.dll

        les def d'attributs sont dans MonAppliQuiContientLesDefs.dll.
        Tu peux également y mettres ton gestionnaire de plugin, celui qui les charges, mais tu peux aussi mettre ton gestionnaire à part. Il se compilera alors de la même façon :
        mcs -target:library monGestionnaire.cs -r:MonAppliQuiContientLesDefs.dll

        ou dans une application :
        mcs monAppli.cs -r:MonAppliQuiContientLesDefs.dll

        en espérant que ca marche mieux maintenant :-)

        Si ca marche toujours pas tu peux me mailer si tu veux.
        • [^] # Re: chezmoicamarche.org

          Posté par  . Évalué à 1.


          Visiblement tu compiles ton plugin avec le source de l'attribute, puis tu recompiles le programme qui cherche les plugins avec ce même source... je me trompes ?
          Donc du coup chacun a sa version de la définition, et malgrès le partage de source, le CLR (Common Langage Runtime, autrement dit l'environnement d'exécution, plus comunément appelé machine virtuelle, qui se lance avec la commande mono) voit 2 versions différentes (ils ont chacuns un numéro de version, etc.)


          C'est exactement ca, apparemment. Merci beaucoup

          Par contre, je ne comprends pas tous les details du probleme. Cela siginifie que la definition de AssemblyDependencies n'est pas la meme pour les differents programmes car au moment ou se fait la compilation (ou l'execution?), une version differente est donnee a AssemblyDependencies par chaque (instance de ?) programme? Bug ou feature? :-)

          J'ai fait tout ce que tu as indique, et ca marche bien, a 2 details pres:
          * l'exe et Plugin.dll doivent etre compiles avec le source code de PluginInterface. Mettre ce code dans une dll commune (avec les defs) ne fonctionne pas: "Cannot find type PluginInterface" a la compilation. Du coup, je retombe sur ce probleme quand dans l'exe j'essaye de voir si Plugin.dll implemente l'interface PluginInterface. Commen regler ca?

          * MonAppliQuiContientLesDefs.dll doit etre dans le meme repertoire que l'exe au lancement. J'imagine que c'est uniquement un probleme de library path, je regarderai ca plus tard.


          Merci beaucoup pour l'aide.
          • [^] # Re: chezmoicamarche.org

            Posté par  (site web personnel) . Évalué à 2.

            Non non c'est pas un bug, c'est une vrai feature, c'est même une des forces de .NET/Mono, c'est cette capacité de versionning (et sa granularité). Tu te doutes bien que'entre différentes applications tu risques de retrouver des noms de classes en communs, des def plus ou moins identiques mais parfois dans un contexte totalement différent. C'est pourquoi le CLR assigne des numéros permettant d'indetifier un assembly, une classe une méthode, plutôt que de se contenter de son nom.
            (celà ne veut pas du tout dire que tu es obligé de signer numériquement tes assembies avec sn.exe)

            Mettre ce code dans une dll commune (avec les defs) ne fonctionne pas: "Cannot find type PluginInterface" a la compilation.
            T'as du te planter quelque part.
            En général chez moi tout ce qui est partagé par les plugins (donc les defs et sans doute ton PluginInterface) sont dans une dll séparée, dans un namespace, comme ceci :

            namespace MonAppli.Core.PluginSystem {
            public interface...
            public attributes...
            }

            (le plus souvent c'est même dans le coeur de mon appli, dans MonAppli.Core.dll)

            et pour développer un plugin, un développeur odit juste référencer ta dll avec mcs :
            mcs -t:library -r:MonAppli.Core.dll

            bien sûr dans son code il doit écrire quelquechose comme :
            using MonAppli.Core.PluginSystem;

            pour "importer" les defs.

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.