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

Delphi Discussion :

Déclaration de pointeur de fonction et structure


Sujet :

Delphi

  1. #1
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 548
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 548
    Points : 25 118
    Points
    25 118
    Par défaut Déclaration de pointeur de fonction et structure
    Voilà, j'ai un petit problème syntaxique

    actuellement, j'ai ceci

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    type
      TShaiMappingStruct = record
        ShaiName : string;        // Champ dans la Table Shai
        DestName: string;         // Champ dans la Table Dest
        SetProc: Pointer;         // Procédure d'Affectation du Champ Dest
        SourceValue: string;      // Champ qui sera comparé au Champ Shai
        DestinationValue: string; // Champ qui sera affecté au Champ Dest
        RelationName: string;     // Champ dans la Table Shai qui sert pour un Test
      end;
      TShaiMappingSetter = procedure(const Item: TShaiMappingStruct; const Source, Destination: TDataSet);
    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
    20
    21
    22
    23
    24
    25
    26
    // Affectation Simple
    procedure StandardSetter(const Item: TShaiMappingStruct; const Source, Destination: TDataSet);
    var
      SourceField, DestinationField: TField;
    begin
      SourceField := Source.FindField(Item.ShaiName);
      DestinationField := Destination.FindField(Item.DestName);
      if Assigned(SourceField) and Assigned(DestinationField) and not SourceField.IsNull and IsEmptyDest(DestinationField) then
        DestinationField.AsVariant := SourceField.AsVariant;
    end;
     
    // Affectation d'une Constante en fonction de la Valeur de la Source
    procedure TestConstSetter(const Item: TShaiMappingStruct; const Source, Destination: TDataSet);
    var
      SourceField, DestinationField: TField;
    begin
      SourceField := Source.FindField(Item.ShaiName);
      DestinationField := Destination.FindField(Item.DestName);
      if Assigned(SourceField) and Assigned(DestinationField) and not SourceField.IsNull and IsEmptyDest(DestinationField) then
      begin
        if SourceField.AsString = Item.SourceValue then
          DestinationField.AsVariant := Item.DestinationValue;
      end;
    end;
     
    // ... Quelques autres Setter encore ...
    j'ai l'association entre les champs et leur fonction

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    const
      Shai_MAPPING : array[TShaiMapping] of TShaiMappingStruct =
      (
        (ShaiName: 'Champ1';                  DestName: 'ChampOne';         SetProc: @TestConstSetter; SourceValue: '...'; DestinationValue: '...'),
        (ShaiName: 'Champ2';                  DestName: 'ChampTwo';         SetProc: @WithoutPointSetter),
        (ShaiName: 'Champ3';                  DestName: 'ChampThree';       SetProc: @StandardSetter),
        (ShaiName: 'Champ4';                  DestName: 'ChampFor';         SetProc: @RelativeSetter;  SourceValue: '...'; RelationName: 'RelationName'),
    ...

    et enfin, j'ai les appels

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
          // Copie des Champs de la Table Shai vers une Autre Table selon le Mapping
          for iMapping := Low(iMapping) to High(iMapping) do
            TShaiMappingSetter(Shai_MAPPING[iMapping].SetProc)(Shai_MAPPING[iMapping], Shai, Destination);
    Le problème c'est que l'on pourrait très vite écrire du code sans aucun contrôle du compilateur, donc je voulais remplacer pointer par le type de procédure ...


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
      TShaiMappingStruct = record
        ShaiName : string;        // Champ dans la Table Shai
        DestName: string;         // Champ dans la Table Dest
        SetProc: TShaiMappingSetter;         // Procédure d'Affectation du Champ Dest
        SourceValue: string;      // Champ qui sera comparé au Champ Shai
        DestinationValue: string; // Champ qui sera affecté au Champ Dest
        RelationName: string;     // Champ dans la Table Shai qui sert pour un Test
      end;
      TShaiMappingSetter = procedure(const Item: TShaiMappingStruct; const Source, Destination: TDataSet);
    Mais peu importe que l'on le mette avant ou après, l'un ne trouve pas l'autre

    alors que ceci fonctionne

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    PShaiMappingStruct = ^TShaiMappingStruct;
    TShaiMappingStruct = record
       ...
    end;
    et je lance un appel juste pour éviter d'écrire

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    type
    PShaiMappingStruct = ^TShaiMappingStruct;
    TShaiMappingSetter = procedure(const Item: PShaiMappingStruct; const Source, Destination: TDataSet);  
    TShaiMappingStruct = record
      end;
    cela permet de retirer l' @ dans le tableau (faut juste en mettre un dans la boucle),
    cela permet de retirer aussi le cast du pointeur en procédure
    cela garanti l'adéquation des paramètres ... mais comme je suis tatillons, je me sens obligé de mettre les ^ pour déférencer les Item explicitement ...

    alors j'ai tenté une autre syntaxe, avec un pointer de procédure mais du coup, cela ne fait la vérification des paramètres ...

    Ma Question est comment faire la même chose sans tricher avec le pointer ...
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  2. #2
    Expert confirmé
    Avatar de anapurna
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2002
    Messages
    3 434
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 434
    Points : 5 846
    Points
    5 846
    Par défaut
    salut

    ce que tu veut faire n'est pas possible de facon statique
    avec les pointer le comilo ne fait pas le test

    sinon une bete question ca n'aurait pas ete plus simple de passer par une class avec des procedure of object

    @+ Phil
    Nous souhaitons la vérité et nous trouvons qu'incertitude. [...]
    Nous sommes incapables de ne pas souhaiter la vérité et le bonheur, et sommes incapables ni de certitude ni de bonheur.
    Blaise Pascal
    PS : n'oubliez pas le tag

  3. #3
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 548
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 548
    Points : 25 118
    Points
    25 118
    Par défaut
    J'ai changé ma Syntaxe, j'ai utilisé la méthode du dernier bloc en trichant avec PShaiMappingStruct, est comme ça dans ma structure j'ai un TShaiMappingSetter au lieu d'un pointeur, donc cela contrôle, ... mais c'est juste que je trouve cela dommage d'avoir la possibilité d'avoir une déclaration forward quand l'on déclare un type de pointeur et pas pour une fonction ... mais bon ...

    avec les pointer le comilo ne fait pas le test
    quel test ?
    celui des paramètres de la procédure
    celui de l'existant du type sur lequel on créé un pointeur ? "PTruc = ^Truc;" car tu peux pas faire un pointeur sur un type qui n'existe pas !

    Sinon pour les Procédure d'objet (genre les gestionnaire d'Events), ... le problème c'est que j'ai du mal à voir comment remplacer mon tableau avec ce principe de classe, ... si tu as une proposition de syntaxe je suis preneur, ... le but étant tout de même d'avoir un code ultra générique et ultra compact ...
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  4. #4
    Expert confirmé
    Avatar de anapurna
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2002
    Messages
    3 434
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 434
    Points : 5 846
    Points
    5 846
    Par défaut
    salut

    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
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    Type
    TProcSetter = Procedure (Sender : Tobject; const Source, Destination:TDataSet) of object;  
     
    TShaiMappingStruct = Class
        ShaiName : string;        // Champ dans la Table Shai
        DestName: string;         // Champ dans la Table Dest
        SourceValue: string;      // Champ qui sera comparé au Champ Shai
        DestinationValue: string; // Champ qui sera affecté au Champ Dest
        RelationName: string;     // Champ dans la Table Shai qui sert pour un Test
        SetProc: TProcSetter;         // Procédure d'Affectation du Champ Dest
       Constructor Create( ShaiName ,DestName, SourceValue,estinationValue
        ,RelationName: string)      
     end;
     
    TarrayShaiMappingStruct =  array of  TShaiMappingStruct;
     
    procedure MyForm.CreateForm(...);
    var 
      Arr : TarrayShaiMappingStruct;
    begin
      setlength(Arr,1);
      arr[0] := TShaiMappingStruct.create('Champ1', 'ChampOne','...','...'   );
      arr[0].SetProc := StandardSetter;
      setlength(Arr,length(Arr));
      arr[high(Arr)] := TShaiMappingStruct.create('Champ2', 'ChampTo','...','...'   );
      arr[high(Arr)].SetProc := TestConstSetter;
      ...
    end;
    // Affectation Simple
    procedure MyForm.StandardSetter(Sender : Tobject; const Source, Destination: TDataSet);
    var
      SourceField, DestinationField: TField;
    begin
      SourceField := Source.FindField(Item.ShaiName);
      DestinationField := Destination.FindField(Item.DestName);
      if Assigned(SourceField) and Assigned(DestinationField) and not SourceField.IsNull and IsEmptyDest(DestinationField) then
        DestinationField.AsVariant := SourceField.AsVariant;
    end;
     
    // Affectation d'une Constante en fonction de la Valeur de la Source
    procedure MyForm.TestConstSetter(Sender : Tobject; const Source, Destination: TDataSet);
    var
      SourceField, DestinationField: TField;
    begin
      SourceField := Source.FindField(Item.ShaiName);
      DestinationField := Destination.FindField(Item.DestName);
      if Assigned(SourceField) and Assigned(DestinationField) and not SourceField.IsNull and IsEmptyDest(DestinationField) then
      begin
        if SourceField.AsString = Item.SourceValue then
          DestinationField.AsVariant := Item.DestinationValue;
      end;
    end;
    quand au test c'est celui de la "coherence" du pointer
    bien sur que si tu dis que c'est un pointer sur le type il faut que celui-ci exist
    mais tu pourrait tous aussi bien

    dire que
    @+ Phil
    Nous souhaitons la vérité et nous trouvons qu'incertitude. [...]
    Nous sommes incapables de ne pas souhaiter la vérité et le bonheur, et sommes incapables ni de certitude ni de bonheur.
    Blaise Pascal
    PS : n'oubliez pas le tag

  5. #5
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 548
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 548
    Points : 25 118
    Points
    25 118
    Par défaut
    Effectivement, ta proposition est exactement ce que je pensais que cela donnerait, c'est extrément long, tu perds l'énumération qui permet de gérer proprement le nombre d'élement, le code à maintenir est plus long (le mapping est sur 30 champs déjà, et non pas que 4 comme mon extrait)

    le Sender : Tobject en TObjet n'a aucun intéret ! il faut caster dans les Setter ... donc on arrive à la possibilité d'erreur d'execition que l'on aurait pu résoudre directement à la compilation, le but était de passer en paramètre un TShaiMappingStruct, tout en ayant TProcSetter dans cette classe, mais avec les classes ce problème ce résoud par une déclaration Forward .

    deplus faudra libérer les objets, donc autant passer par une TObjectList au lieu d'un tableau évidemmeent ...

    Désolé d'être aussi critique, je cherche vraiement le code le plus "optimum" car on a bcp de code inutile dans notre programme qui pourrait être refactorer avec une méthode standardisée comme celle-ci
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  6. #6
    Expert confirmé
    Avatar de anapurna
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2002
    Messages
    3 434
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 434
    Points : 5 846
    Points
    5 846
    Par défaut
    salut

    Tu peut Peut etre dans ce cas passer une list de champs plutot
    que de passer champs par champs

    je ne t'ai donnée qu'une des possibilite ne connaissant pas le probleme dans ca globalite

    le sender peut avoir un interet pour connaitre l'element declanchant
    si tu nomme tes objects

    tu peut aussi passer par une collection si tu lui passe des tfield
    ou encore par un tableau de champs

    il y as une multitude de solution

    @+ Phil
    Nous souhaitons la vérité et nous trouvons qu'incertitude. [...]
    Nous sommes incapables de ne pas souhaiter la vérité et le bonheur, et sommes incapables ni de certitude ni de bonheur.
    Blaise Pascal
    PS : n'oubliez pas le tag

  7. #7
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 548
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 548
    Points : 25 118
    Points
    25 118
    Par défaut
    L'Objectif c'est :
    Une Table Source doit être recopiée dans une Table Destination, Le nom des Champs est différent, les valeurs sont stockés différement aussi, par exemple les Booleans sont dans l'une un Integer, dans l'autre un Char, ... le nombre de champ aujourd'hui approche la trentaine, demain, il peut y en avoir deux fois plus, avec de nouvelle façon de convertir
    Il existe des modules de recodages, de stat et autre dans la lib de mon employeur, mais j'ai un peu de mal à les utiliser et dans cette utilisation, on me les a déconseillé ...

    Ensuite, j'ai tenté la figure de Style, faut être honnête, j'ai cherché à avoir le code plus court que possible !!! et la variante objet dans tous les cas est plus longue et surtout le plus important c'est le Tableau en Constante sans code annexe plus complexe qu'une simple déclaration ...
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  8. #8
    Expert confirmé
    Avatar de anapurna
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2002
    Messages
    3 434
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 434
    Points : 5 846
    Points
    5 846
    Par défaut
    salut

    dans ton cas je travailerai par ecxeption

    une bete copie de ligne se faite de cet maniere

    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
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
     
      if dtsetsrc.active = true and dtsetdest.active = true then
      begin
        count :=  dtsetsrc.FieldCount-1;
        For i:= 0 To count Do
        begin
          if not(dtsetdest.state in [dsinsert,dsedit]) then
            dtsetdest.edit;
          try
    	if (dtsetsrc.Fields[i].FieldKind = fkData) then
    	begin
    	  if dtsetdest.FindField(DonneName(dtsetsrc.Fields[i].FieldName)) <> nil then
    	     IF lstChpspec.indexof(DonneName(dtsetsrc.Fields[i].FieldName))< 0 Then // pas trouve = -1
    	        dtsetdest.FindField(DonneName(dtsetsrc.Fields[i].FieldName)).Value := dtsetsrc.Fields[i].Value
    	     else
    	       dtsetdest.FindField(DonneName(dtsetsrc.Fields[i].FieldName)).Value := DonneValue(dtsetsrc.Fields[i]) ;
            end;
          except
          end;
        end;
      end;
    end;
     
    function DonneValue(Field :Tfield) : variant;
    begin
      //
    end
     
    function DonneName(st : String) : String;
    begin
     //
    end
    j'ai simplifie mais cest pas si compliquée

    @+ Phil
    Nous souhaitons la vérité et nous trouvons qu'incertitude. [...]
    Nous sommes incapables de ne pas souhaiter la vérité et le bonheur, et sommes incapables ni de certitude ni de bonheur.
    Blaise Pascal
    PS : n'oubliez pas le tag

  9. #9
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 548
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 548
    Points : 25 118
    Points
    25 118
    Par défaut
    La Boucle qui je mis sur le forum est encadré par bcp de chose, et cela remplace ce code

    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
    20
    for iField := 0 to Source.FieldCount - 1 do
    begin
       if Destination.FieldNum(Source.Fields[iField].FieldName) > 0 then
       begin
          if (Trim(Source.Fields[iField].AsString) <> '')
          and (Destination.FieldByName(Source.Fields[iField].FieldName).isNull
            or (Trim(Destination.FieldByName(Source.Fields[iField].FieldName).AsString) = '')) then
          begin
             if InPos(Source.Fields[iField].FieldName, 'Truc|Truc|Truc|Truc') then
             begin
                Destination.FieldByName(Source.Fields[iField].FieldName).AsString
                   := AnsiReplaceText(Source.FieldByName(Source.Fields[iField].FieldName).AsString, '.', '');
             end else
             begin
                Destination.FieldByName(Source.Fields[iField].FieldName).AsString
                   := Source.FieldByName(Source.Fields[iField].FieldName).AsString;
             end;
          end;
       end;
    end;
    Le problème c'est le code de DonneValue et DonneName qui seront qu'un gros case ou un enchevetrement de if, difficilement maintenable ... et ce que je cherche c'est une écriture très compacte ...

    alors je suis preneur pour une syntaxe ultra clean de DonneValue pour gérer 30 champs et 7 formes de setter aujourd'hui et peut-être 100 champ et 15 setters ...
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  10. #10
    Expert confirmé
    Avatar de anapurna
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2002
    Messages
    3 434
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 434
    Points : 5 846
    Points
    5 846
    Par défaut
    salut

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    TSetProc = Procedure (SourceField, DestinationField : Field) of object
     
    function TMyobj.ExecProc(aSourceField, aDestinationField : Tfiled;MyProcStr : String):boolean;
    Var
      SetProc : TSetProc;
    Begin
      TMethod(myProc).data:=self;
      TMethod(MyProc).code :=MethodAddress(MyProcStr);
      result:=true;
       if Assigned(SetProc) Then
         SetProc(aSourceField,aDestinationField);
    end;
    avec un tableau de trois colonne tu devrais pouvoir t'en sortir
    voila la tructure du tableau
    StrChpsrc,StrChpDest,NameSetter ce ne sont que des string

    il ne te reste qu'a mettre les setter en published

    @+ Phil
    Nous souhaitons la vérité et nous trouvons qu'incertitude. [...]
    Nous sommes incapables de ne pas souhaiter la vérité et le bonheur, et sommes incapables ni de certitude ni de bonheur.
    Blaise Pascal
    PS : n'oubliez pas le tag

  11. #11
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 548
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 548
    Points : 25 118
    Points
    25 118
    Par défaut
    Oui, j'avais pensé d'utiliser le RTTI comme je le fais pour mon modèle de persistance (dans le principe InstantObject) que j'ai développé au bureau ...

    mais, on en revient à perdre le contrôle de paramètres des méthodes identifier par le nom ... ma dernière variante de syntaxe permet d'éviter que cette méthode soit compiler :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    procedure InvalideSetter(AutreParam: TMachin);
    parce que le prototype DOIT être
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    procedure(const Item: PShaiMappingStruct; const Source, Destination: TDataSet);
    sinon, on perd aussi les paramètres auxiliaires utilisés dans les setters, car tu peux lire dans la source en fonction d'un autre champs pour écrire dans la destination ...
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  12. #12
    Expert confirmé
    Avatar de anapurna
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2002
    Messages
    3 434
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 434
    Points : 5 846
    Points
    5 846
    Par défaut
    salut

    Pouquoi doit tu a tout pris prendre le dataset ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    TShaiMappingStruct = record
        ShaiName : string;        // <= C'est quoi ce champs ?
        DestName: string;         // Champ dans la Table Dest
        SetProc: TShaiMappingSetter;  // <= ne peut tu pas simplement le remplacer par le nom du setter ?
        SourceValue: string;      // Champ qui sera comparé au Champ Shai
        DestinationValue: string; // le Champ source ne vas pas etre transformé ?
        RelationName: string;     // Test ???
      end;
    moi je l'aurai vu simplement comme cela

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    TShaiMappingStruct = record
        Sourcename : string;     // Champ dans la table source 
        DestName   : string;      // Champ dans la Table Dest
        SetProc: string;            // nom du setter ?
      end;
    les Field etant Facilement Trouvable avec findfield

    sinon, on perd aussi les paramètres auxiliaires utilisés dans les setters, car tu peux lire dans la source en fonction d'un autre champs pour écrire dans la destination ...
    C'est dans la table source ou c'est une autre table
    ma fonction est applicable une foie que tu a defini quelle champs source doit etre mis dans le champs destination

    au final tu n'as que deux champs qui sont en presence a moins que tu ne fasse un cumul de champs mais dans ce cas il faut peut etre revoir l'obtention de tes donnée


    @+ phil
    Nous souhaitons la vérité et nous trouvons qu'incertitude. [...]
    Nous sommes incapables de ne pas souhaiter la vérité et le bonheur, et sommes incapables ni de certitude ni de bonheur.
    Blaise Pascal
    PS : n'oubliez pas le tag

  13. #13
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 548
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 548
    Points : 25 118
    Points
    25 118
    Par défaut
    Le problème du Nommage, c'est que je perd un avantage de typé les procédures qui est qu'a la Compilation cela détecte les Erreurs sur les paramètres des Setters

    Et les Setters font des calculs, par exemple TestConstSetter (fourni ci-dessu) test l'égalité à une valeur de la source pour affecter une toute autre valeur à la destination ... c'est du recodage

    et un autre va tester sur un troisieme champ est supérieur à une valeur pour recopier la source dans la destination ... c'est de l'affectation conditionnelle ...

    un autre setter va convertir les format de Date, les formats de flottant ...
    SourceValue, DestinationValue et RelationName ne sont pas la que pour faire joli, exmple ce setter :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    procedure RelativeSetter(const Item: PCrisapMappingStruct; const Source, Destination: TDataSet);
    var
      SourceField, DestinationField, RelationField: TField;
    begin
      SourceField := Source.FindField(Item^.ShaiName);
      DestinationField := Destination.FindField(Item^.KsName);
      RelationField := Source.FindField(Item^.RelationName);
      if Assigned(SourceField) and Assigned(DestinationField) and Assigned(RelationField) and not SourceField.IsNull and IsEmptyDest(DestinationField) then
      begin
        if RelationField.AsString = Item^.SourceValue then
          DestinationField.AsVariant := SourceField.AsVariant;
      end;
    end;
    je crois que je vais continuer à tricher avec PCrisapMappingStruct pour déclarer ma TShaiMappingStruct contenant TShaiMappingSetter, ça fait ce que j'ai besoin et c'est Safe-Compilation ce qui est l'un des critères de cette "architecture de code"
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  14. #14
    Expert confirmé
    Avatar de anapurna
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2002
    Messages
    3 434
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 434
    Points : 5 846
    Points
    5 846
    Par défaut
    salut

    il te suffit donc de modifier ExecProc

    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
    20
    TShaiMappingStruct = record
        ShaiName : string;        // <= C'est quoi ce champs ?
        DestName: string;         // Champ dans la Table Dest
        SetProc: string;     // le nom du setter 
        SourceValue: string;      // Champ qui sera comparé au Champ Shai
        DestinationValue: string; // le Champ source ne vas pas etre transformé ?
        RelationName: string;     // Test ???
      end;
     
    function TMyobj.ExecProc(Item : TShaiMappingStruct;
     ; const Source, Destination: TDataSet):boolean;
    Var
      SetProc : TSetProc;
    Begin
      TMethod(myProc).data:=self;
      TMethod(MyProc).code :=MethodAddress(Item.SetProc);
      result:=true;
       if Assigned(SetProc) Then
          SetProc(item,Source, Destination);
    end;
    Nous souhaitons la vérité et nous trouvons qu'incertitude. [...]
    Nous sommes incapables de ne pas souhaiter la vérité et le bonheur, et sommes incapables ni de certitude ni de bonheur.
    Blaise Pascal
    PS : n'oubliez pas le tag

  15. #15
    Membre confirmé
    Avatar de gb_68
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2006
    Messages
    232
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2006
    Messages : 232
    Points : 546
    Points
    546
    Par défaut
    Bonjour,

    pour en revenir au record, une solution pourrait être :
    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
    20
    21
    22
      TShaiMappingData = record
        ShaiName : string;        // Champ dans la Table Shai
        DestName: string;         // Champ dans la Table Dest
        SourceValue: string;      // Champ qui sera comparé au Champ Shai
        DestinationValue: string; // Champ qui sera affecté au Champ Dest
        RelationName: string;     // Champ dans la Table Shai qui sert pour un Test
      end;
     
      TShaiMappingSetter = procedure(const Item: TShaiMappingData; const Source, Destination: TDataSet);
     
      TShaiMappingStruct = record
        FSetProc : TShaiMappingSetter;
        FShaiMappingStruct : TShaiMappingData;
        procedure SetProc (const Source, Destination: TDataSet );inline;
      end;
     
    { TShaiMappingStruct }
     
    procedure TShaiMappingStruct.SetProc(const Source, Destination: TDataSet);
    begin
        FSetProc(FShaiMappingStruct,Source, Destination);
    end;
    bon ça fait un type en plus (TShaiMappingData), mais ça reste assez lisible

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    const Shai_MAPPING : array[TAILLE] of TShaiMappingStruct = (
               ( FShaiMappingStruct : ( ShaiName    : '' ; DestName         : '' ;
                                        SourceValue : '' ; DestinationValue : '' );
                 FSetProc : @UneProcedure ); {...}

    avec pour appeler la fonction :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    for iMapping := Low(Shai_MAPPING) to High(Shai_MAPPING) do
            Shai_MAPPING[iMapping].SetProc( Shai , Destination );
    {évite en outre d'appeler Shai_MAPPING[i].SetProc sur Shai_MAPPING[j].FShaiMappingStruct avec i<>j}
    ou plus court :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    var ShaiMS : TShaiMappingStruct;
    {...}
    for ShaiMS in Shai_MAPPING do
        ShaiMS.SetProc( Shai , Destination );

  16. #16
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 548
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 548
    Points : 25 118
    Points
    25 118
    Par défaut
    gb_68, décomposé la structure en deux parties, hum, efficace, simple, en fait c'est absolument la meilleure solution

    sinon "for ShaiMS in Shai_MAPPING do", Delphi 2005 ? Je suis en D6 ou D7, ... j'ai tellement l'habitude du Low High sur Enum que ça me dérange pas

    {évite en outre d'appeler Shai_MAPPING[i].SetProc sur Shai_MAPPING[j].FShaiMappingStruct avec i<>j}
    Euh, j'ai pas bien compris cette remarque !?

    et le "inline" ? Selon l'aide de Delphi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Le mot réservé inline et la directive assembler ne sont conservés que dans un souci de compatibilité ascendante. Ils sont ignorés par le compilateur.
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  17. #17
    Membre confirmé
    Avatar de gb_68
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2006
    Messages
    232
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2006
    Messages : 232
    Points : 546
    Points
    546
    Par défaut
    Un petit 'Assigned' pour faire propre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    procedure TShaiMappingStruct.SetProc(const Source, Destination: TDataSet);
    begin
        if Not Assigned( FSetProc ) then raise Exception.Create('invalide FSetProc');
        FSetProc(FShaiMappingStruct,Source, Destination);
    end;

  18. #18
    Expert confirmé
    Avatar de anapurna
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2002
    Messages
    3 434
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 434
    Points : 5 846
    Points
    5 846
    Par défaut
    salut

    tu veut a tout pris passer par les pointer alors que moi je te donne le solution en passant simplement par des string c'est quand meme dingue de voir ca

    @+ phil
    Nous souhaitons la vérité et nous trouvons qu'incertitude. [...]
    Nous sommes incapables de ne pas souhaiter la vérité et le bonheur, et sommes incapables ni de certitude ni de bonheur.
    Blaise Pascal
    PS : n'oubliez pas le tag

  19. #19
    Membre confirmé
    Avatar de gb_68
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2006
    Messages
    232
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2006
    Messages : 232
    Points : 546
    Points
    546
    Par défaut
    Oui c'est du Delphi 2005 (le for .. in )

    le inline aussi :
    Utilisation de la directive inline
    Pour améliorer les performances, le compilateur Delphi permet le balisage des fonctions et procédures à l'aide de la directive inline. Si une fonction ou procédure répond à certains critères, le compilateur insère directement le code au lieu de générer un appel. L'utilisation de cette directive induit une optimisation des performances pouvant se traduire par un code plus rapide, mais elle présente des inconvénients en termes d'espace. En effet, elle entraîne toujours la création d'un fichier binaire plus volumineux par le compilateur. Comme les autres directives, la directive inline est utilisée dans les déclarations et définitions de fonctions et de procédures.
    procedure MyProc(x:Integer); inline;
    begin
    // ...
    end;

    function MyFunc(y:Char) : String; inline;
    begin
    // ..
    end;
    mais
    L'utilisation de la directive inline par le compilateur n'est qu'une suggestion.En effet, il n'existe aucune garantie quant à son utilisation par le compilateur pour une routine particulière car, dans certains cas, cette directive ne peut pas être employée.
    Pour le
    {évite en outre d'appeler Shai_MAPPING[i].SetProc sur Shai_MAPPING[j].FShaiMappingStruct avec i<>j}
    c'était pour le premier post :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    TShaiMappingSetter(Shai_MAPPING[iMapping].SetProc)(Shai_MAPPING[iMapping], Shai, Destination);
    rien n'empêche de faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    TShaiMappingSetter(Shai_MAPPING[i].SetProc)(Shai_MAPPING[j], Shai, Destination);
    avec un i et un j différents (mais c'est peut-être le but recherché ?).

  20. #20
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 548
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 548
    Points : 25 118
    Points
    25 118
    Par défaut
    @anapurna : Justement je n'ai AUCUN pointeur mais un type de procédure qui permet de détecter les erreurs à la compilation, ce qui est dingue ce que tu n'arrive pas à comprendre que tes solutions ne sont pas "vérifié" pour les prototypes de fonction à la compilation donc cela peut provoquer des erreurs et fait perdre du temps à la maintenance

    @gb_68, c'est le vrai inline de c, j'avais cru l'avoir trouvé en Delphi, ouais ça c'est une bonne chose, à tester si en D7 le inline n'aurait pas un effet quand même ...

    et sinon pour la remarque sur les indices, c'est bien vu, je n'avais pas vu la subtilité ... je vais au ciné, mais les premiers essais de compilation et de run sont concluant ...
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. classe sans déclaration et pointeur de fonction
    Par Asmod_D dans le forum C++
    Réponses: 3
    Dernier message: 27/06/2010, 16h39
  2. structures et pointeurs de fonctions
    Par aimad41 dans le forum C
    Réponses: 5
    Dernier message: 21/11/2006, 10h49
  3. Structure, pointeur et fonction...
    Par Linaa dans le forum C
    Réponses: 15
    Dernier message: 04/12/2005, 13h12
  4. Pointeur de fonction et structure
    Par Trunks dans le forum C
    Réponses: 6
    Dernier message: 07/10/2005, 00h32
  5. Réponses: 4
    Dernier message: 08/02/2005, 20h47

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