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 :

Modifier des fichiers CS par programme.


Sujet :

C#

  1. #1
    Expert confirmé
    Avatar de popo
    Homme Profil pro
    Analyste programmeur Delphi / C#
    Inscrit en
    Mars 2005
    Messages
    2 672
    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 : 2 672
    Points : 5 253
    Points
    5 253
    Par défaut Modifier des fichiers CS par programme.
    Bonjour,

    Je cherche des pistes pour modifier trois fichiers CS par programme.
    Au départ j'ai un template T4 qui me génères 3 fichiers à partir du nom d'une table de ma base de données.
    Il s'agit d'un vielle version du template POCO generator que j'ai adapté à mes besoins.
    https://marketplace.visualstudio.com...ePOCOGenerator

    J'ai un premier fichiers qui ressemble à ceci :
    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
        [Table("KUNDE", Schema = "dbo")]
        [System.CodeDom.Compiler.GeneratedCode("EF.Reverse.POCO.Generator", "2.36.1.0")]
        public class Kunde : Entity
        {
            [DatabaseGenerated(DatabaseGeneratedOption.None)]
            [Column(@"K_Code", Order = 1, TypeName = "varchar")]
            [Index(@"K_Code", 2, IsUnique = true, IsClustered = false)]
            [MaxLength(17)]
            [StringLength(17)]
            [Key]
            [Display(Name = "Code")]
            public string Code { get; set; }
     
            [NotMapped]
            [Column(@"K_Vorname", Order = 2, TypeName = "varchar")]
            [Index(@"K_Vorname", 1, IsUnique = false, IsClustered = false)]
            [MaxLength(35)]
            [StringLength(35)]
            [Display(Name = "Vorname")]
            public string Vorname { get; set; }
     
            [NotMapped]
            [Column(@"K_Anderungsdatum", Order = 3, TypeName = "datetime")]
            [Display(Name = "Änderungsdatum")]
            public System.DateTime Anderungsdatum { get; set; }
    }
    Où l'objectif est le suivant :
    - repérer l'attribut Column portant le nom d'une colonne en particulier (exemple K_Vorname)
    - enlever l'attribut NotMapped sur la propriété correspondante
    - changer le nom de la propriété en FirstName

    Un deuxième qui ressemble à ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
        [System.CodeDom.Compiler.GeneratedCode("EF.Reverse.POCO.Generator", "2.36.1.0")]
        public class Kunde Configuration : System.Data.Entity.ModelConfiguration.EntityTypeConfiguration<Kunde>
        {
            public KundeConfiguration()
                : this("dbo")
            {
            }
     
            public KundeConfiguration(string schema)
            {
                Property(x => x.Code).IsUnicode(false); // K_Code
                //Property(x => x.Vorname).IsOptional().IsUnicode(false); // K_Vorname
                //Property(x => x.Anderungsdatum).IsOptional(); // K_Anderungsdatum
           }
    Où l'objectif est le suivant :
    - repérer le commentaire portant le nom d'une colonne en particulier (exemple K_Vorname)
    - Enlever le commentaire au début de la ligne
    - changer le nom de la propriété en FirstName
    - Certaines colonnes notamment celles de type Entier sont potentiellement absentes de ce fichier.

    Et le troisième qui ressemble à ceci :
    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
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
         [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Justification = "They are fields names")]
        public static class KundeTableInformationStore
    	{
    		/* CA1024 (Design) 
    		 * Use property if appropriate */
    		public static ODataTableInformationModel TableAndFields
    		{
    			get { return GetTableAndFields(); }
    		}
     
    		private static ODataTableInformationModel GetTableAndFields()
    		{
    			ODataTableInformationModel result = new ODataTableInformationModel()
    			{
    				Name = "Kunde",
                                    InternalName = "KUNDE",
    				Description = "Kunden",
    				Prefix = "K",
                                    Key = "K_Code",
    				Fields = GetFieldsOnly()
    			};
     
     
    			return result;
    		}
     
    		/* CA1024 (Design) 
    		 * Use property if appropriate */
    		public static System.Collections.Generic.IEnumerable<ODataFieldInformationModel> Fields
    		{
    			get { return GetFieldsOnly(); }
    		}
     
    		private static System.Collections.Generic.IEnumerable<ODataFieldInformationModel> GetFieldsOnly()
    		{
    			return new System.Collections.Generic.List<ODataFieldInformationModel>()
    				{
                        new ODataFieldInformationModel()
                        {
                            TableName = "KUNDE",
                            Name = "Code",
                            InternalName = "K_Code",
                            Description = "Code",
                            DataType = "VARCHAR(17)",
                            Mapped = true
                        },
                        new ODataFieldInformationModel()
    					{
    						TableName = "KUNDE", 
    						Name = "Vorname",
    						InternalName = "K_Vorname",
    						Description = "Vorname",
    						DataType = "VARCHAR(35)"
                        },
    					new ODataFieldInformationModel()
    					{
    						TableName = "KUNDE", 
    						Name = "Änderungsdatum",
    						InternalName = "K_Anderungsdatum",
    						Description = "Änderungsdatum",
    						DataType = "DATE"
                        },
                }
          }
    Où l'objectif est le suivant :
    -Changer la valeur de la propriété Name en mettant "Customer" dans l'objet ODataTableInformationModel utilisé dans GetTableAndFields
    - idem pour la propriété Description où il faut mettre "Customers"
    -Changer la valeur de la propriété Name en mettant "FirstName" dans l'objet ODataFieldInformationModel utilisé dans GetFieldsOnly
    - idem pour la propriété Description où il faut mettre "First Name"
    - Ajouter une propriété Mapped avec la valeur true

    Aujourd'hui je dois faire tous ces changements à la main et pas uniquement pour une seule colonne mais plusieurs dizaines réparties dans plusieurs tables
    C'est un processus long et source d'erreurs et j'aimerai l'automatiser.
    Existe-il un librairie me permettant de faire simplement et surtout automatiquement ces modifications ?

    Merci.

  2. #2
    Expert éminent
    Avatar de Immobilis
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Mars 2004
    Messages
    6 559
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Mars 2004
    Messages : 6 559
    Points : 9 506
    Points
    9 506
    Par défaut
    Et tu ne peux pas modifier le template T4 pour le faire?
    Sinon, tu peux utiliser les expressions régulières.
    "Winter is coming" (ma nouvelle page d'accueil)

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

    Informations professionnelles :
    Activité : edi

    Informations forums :
    Inscription : Juin 2007
    Messages : 898
    Points : 1 915
    Points
    1 915
    Par défaut
    Si ce sont des entités pour des bases de données tu peux peut-être voir avec EF Core Power Tools (je ne sais plus s'il y a l'équivalent pour .Net Framework). Sinon ça m'arrive de faire de manipulations de lignes de texte avec Notepad++ à base de patterns et de regex, mais je ne sais pas si ce sera suffisant pour répondre à ton besoin.

  4. #4
    Expert confirmé
    Avatar de popo
    Homme Profil pro
    Analyste programmeur Delphi / C#
    Inscrit en
    Mars 2005
    Messages
    2 672
    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 : 2 672
    Points : 5 253
    Points
    5 253
    Par défaut
    Immobilis,
    Je pourrais éventuellement modifier le template.
    Mais cela signifie que si on me demande de publier d'autres champs après coup, il faudrait que j'ai quelque part une trace de l'existant et que je fasse manuellement le tri entre ce qui est déjà publié et ce qui ne l'est pas. Ou alors nommer également les champs qui ne seront pas publiés pour tous les traiter sans risque et avoir l'information de ce qui sera publié ou non, alors que l'idée était simplement de fournir une liste de nouveau champs à publier. Ce sont deux solutions que je voulais éviter car elle incluent toutes deux une charge de travail manuelle en plus (certes moindres qu'actuellement) alors que le but est d'automatiser tout ce qui peut l'être. La correspondance des noms devra être faite manuellement quoi que je fasse mais si je peux éviter de devoir trier manuellement ou de nommer des choses inutile, ce serait mieux.

    J'aime bien l'idée des expressions régulières mais je ne les maîtrise pas et, je me trompe peut-être mais ça ne me permettra uniquement de retrouver la ligne portant le nom de la colonne.
    En quoi cela va m'aider à virer un commentaire ou à ajouter une propriété à un objet existant ?

    Noxen,
    Le Reverse Engineer propose par EF Core Power Tools fait à peu près la même chose que ce que j'utilise actuellement.
    Je vais donc me retrouver avec le même problème à la fin.
    Quand à notepad++, cela reste manuel.


    Mon idée de départ était d'avoir un fichier Excel par table (ou une feuille par table dans un seul fichier Excel) qui contiendrai la correspondance des noms (uniquement ceux que je souhaite mapper à un instant T)
    Puis avec un bout de script ou un programme faire le travail que fait aujourd'hui manuellement.
    L'objectif était de ne jouer le template qu'une seule fois par table (car il écrase tout) et de passer derrière pour modifier ce qui a été généré.

    J'ai donc recherché des librairies pour lire un fichier CS ou un exemple de script Powershell.
    Mais n'ayant rien trouvé je me suis dis que ce n'était peut-être pas la bonne méthode et me voila.

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

    Informations professionnelles :
    Activité : edi

    Informations forums :
    Inscription : Juin 2007
    Messages : 898
    Points : 1 915
    Points
    1 915
    Par défaut
    Je me suis amusé un peu avec Roslyn, je ne sais pas si c'est possible pour toi, ça a l'air de donner quelque-chose de correct pour le premier fichier (l'entité Kunde) :

    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
    53
    54
    55
    56
    57
    58
    59
    60
    61
    using System.IO;
    using System.Linq;
    using Microsoft.CodeAnalysis;
    using Microsoft.CodeAnalysis.CSharp;
    using Microsoft.CodeAnalysis.CSharp.Syntax;
     
    namespace CodeTransform
    {
        class Program
        {
            static void Main(string[] args)
            {
                var source = "Kunde.cs";
                var destination = "Kunde.v2.cs";
     
                var columnName = "K_Vorname";
                var newPropertyName = "FirstName";
     
                source.Read()
                        .Parse()
                        .Transform(columnName, newPropertyName)
                        .ToString()
                        .Write(destination);
            }
        }
     
        static class CodeExtensions
        {
            internal static string Read(this string filePath) => File.ReadAllText(filePath);
            internal static SyntaxTree Parse(this string code) => CSharpSyntaxTree.ParseText(code);
            internal static SyntaxTree Transform(this SyntaxTree tree, string columnName, string newPropertyName) =>
                SyntaxFactory.SyntaxTree(tree.GetRoot().Transform(columnName, newPropertyName));
            internal static void Write(this string code, string filePath) => File.WriteAllText(filePath, code); 
     
            internal static SyntaxNode Transform(this SyntaxNode node, string columnName, string newPropertyName)
            {
                var oldProp = node.SelectProperty(columnName);
                return node.ReplaceNode(oldProp, oldProp.Transform(newPropertyName));
            }
     
            internal static SyntaxNode Transform(this PropertyDeclarationSyntax prop, string newPropertyName) => prop
                    .RemoveNode(prop.SelectAttributeNodeContaining("NotMapped"), SyntaxRemoveOptions.KeepTrailingTrivia)
                    .WithIdentifier(SyntaxFactory.Identifier(newPropertyName));
     
            internal static SyntaxNode SelectAttributeNodeContaining(this SyntaxNode node, string pattern) =>
                node.RecognizeAttribute(pattern) ?
                node.Parent :
                node.ChildNodes().Select(n => n.SelectAttributeNodeContaining(pattern)).FirstOrDefault(n => n != null);
     
            internal static bool RecognizeAttribute(this SyntaxNode node, string pattern) =>
                node.IsKind(SyntaxKind.Attribute) &&
                ((AttributeSyntax)node).GetText().ToString().Contains(pattern);
     
            internal static PropertyDeclarationSyntax SelectProperty(this SyntaxNode node, string columnName)
            {
                var att = node.SelectAttributeNodeContaining(columnName);
                var prop = att.Parent;
                return (PropertyDeclarationSyntax)prop;
            }
        }
    }
    Avant :

    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
    [Table("KUNDE", Schema = "dbo")]
    [System.CodeDom.Compiler.GeneratedCode("EF.Reverse.POCO.Generator", "2.36.1.0")]
    public class Kunde : Entity
    {
        [DatabaseGenerated(DatabaseGeneratedOption.None)]
        [Column(@"K_Code", Order = 1, TypeName = "varchar")]
        [Index(@"K_Code", 2, IsUnique = true, IsClustered = false)]
        [MaxLength(17)]
        [StringLength(17)]
        [Key]
        [Display(Name = "Code")]
        public string Code { get; set; }
     
        [NotMapped]
        [Column(@"K_Vorname", Order = 2, TypeName = "varchar")]
        [Index(@"K_Vorname", 1, IsUnique = false, IsClustered = false)]
        [MaxLength(35)]
        [StringLength(35)]
        [Display(Name = "Vorname")]
        public string Vorname { get; set; }
     
        [NotMapped]
        [Column(@"K_Anderungsdatum", Order = 3, TypeName = "datetime")]
        [Display(Name = "Änderungsdatum")]
        public System.DateTime Anderungsdatum { get; set; }
    }
    Après :
    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
    [Table("KUNDE", Schema = "dbo")]
    [System.CodeDom.Compiler.GeneratedCode("EF.Reverse.POCO.Generator", "2.36.1.0")]
    public class Kunde : Entity
    {
        [DatabaseGenerated(DatabaseGeneratedOption.None)]
        [Column(@"K_Code", Order = 1, TypeName = "varchar")]
        [Index(@"K_Code", 2, IsUnique = true, IsClustered = false)]
        [MaxLength(17)]
        [StringLength(17)]
        [Key]
        [Display(Name = "Code")]
        public string Code { get; set; }
     
        [Column(@"K_Vorname", Order = 2, TypeName = "varchar")]
        [Index(@"K_Vorname", 1, IsUnique = false, IsClustered = false)]
        [MaxLength(35)]
        [StringLength(35)]
        [Display(Name = "Vorname")]
        public string FirstName{ get; set; }
     
        [NotMapped]
        [Column(@"K_Anderungsdatum", Order = 3, TypeName = "datetime")]
        [Display(Name = "Änderungsdatum")]
        public System.DateTime Anderungsdatum { get; set; }
    }
    Vous êtes dans une phase de renommage de votre historique de code depuis l'allemand vers l'anglais ?

  6. #6
    Expert confirmé
    Avatar de popo
    Homme Profil pro
    Analyste programmeur Delphi / C#
    Inscrit en
    Mars 2005
    Messages
    2 672
    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 : 2 672
    Points : 5 253
    Points
    5 253
    Par défaut
    Merci Noxen, ça à l'air prometteur !

    En fait, la structure de la base est en allemand.
    On me demande de rendre accessible via des API ODATA une partie de cette base telle qu'elle est décrite.
    Mais en anglais, pas en allemand.

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

    Informations professionnelles :
    Activité : edi

    Informations forums :
    Inscription : Juin 2007
    Messages : 898
    Points : 1 915
    Points
    1 915
    Par défaut
    Citation Envoyé par popo Voir le message
    Merci Noxen, ça à l'air prometteur !
    Pour moi c'est une découverte, c'est la première fois que j'utilise Roslyn, je ne suis pas sûr que mon approche soit très idiomatique. En plus ça ne gère pas par exemple le renommage des référence.

    J'ai réussi à faire quelque chose pour le deuxième fichier, même si je n'en suis pas encore satisfait (je préfèrerais éviter de reconstruire l'arbre syntaxique en faisant un parsing du texte modifié).

    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
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    using System.IO;
    using System.Linq;
    using Microsoft.CodeAnalysis;
    using Microsoft.CodeAnalysis.CSharp;
    using Microsoft.CodeAnalysis.CSharp.Syntax;
     
    namespace CodeTransform
    {
        class Program
        {
            static void Main(string[] args)
            {
                var columnName = "K_Vorname";
                var oldPropertyName = "Vorname";
                var newPropertyName = "FirstName";
                TransformEntity("Kunde.cs", "Kunde.v2.cs", columnName, newPropertyName);
                TransformConfiguration("KundeConfiguration.cs", "KundeConfiguration.v2.cs", columnName, oldPropertyName, newPropertyName);
            }
     
            static void TransformEntity(string source, string destination, string columnName, string newPropertyName) =>
                source
                .Read()
                .Parse()
                .TransformEntity(columnName, newPropertyName)
                .ToString()
                .Write(destination);
     
            static void TransformConfiguration(string source, string destination, string columnName, string oldPropertyName, string newPropertyName) =>
                source
                .Read()
                .Parse()
                .TransformConfiguration(columnName, oldPropertyName, newPropertyName)
                .ToString()
                .Write(destination);
        }
     
        static class CodeExtensions
        {
            internal static string Read(this string filePath) => File.ReadAllText(filePath);
            internal static SyntaxTree Parse(this string code) => CSharpSyntaxTree.ParseText(code);
            internal static void Write(this string code, string filePath) => File.WriteAllText(filePath, code);
     
            #region Entity
            internal static SyntaxTree TransformEntity(this SyntaxTree tree, string columnName, string newPropertyName) =>
                SyntaxFactory.SyntaxTree(tree.GetRoot().TransformProperty(columnName, newPropertyName));
     
            internal static SyntaxNode TransformProperty(this SyntaxNode node, string columnName, string newPropertyName)
            {
     
                var oldProp = node.SelectProperty(columnName);
                return node.ReplaceNode(oldProp, oldProp.Transform(newPropertyName));
            }
     
            internal static PropertyDeclarationSyntax SelectProperty(this SyntaxNode node, string columnName)
            {
                var att = node.SelectAttributeNodeContaining(columnName);
                var prop = att.Parent;
                return (PropertyDeclarationSyntax)prop;
            }
     
            internal static SyntaxNode Transform(this PropertyDeclarationSyntax prop, string newPropertyName) => prop
                   .RemoveNode(prop.SelectAttributeNodeContaining("NotMapped"), SyntaxRemoveOptions.KeepTrailingTrivia)
                   .WithIdentifier(SyntaxFactory.Identifier(newPropertyName));
     
            internal static SyntaxNode SelectAttributeNodeContaining(this SyntaxNode node, string pattern) =>
                node.RecognizeAttribute(pattern) ?
                node.Parent :
                node.ChildNodes().Select(n => n.SelectAttributeNodeContaining(pattern)).FirstOrDefault(n => n != null);
     
            internal static bool RecognizeAttribute(this SyntaxNode node, string pattern) =>
                node.IsKind(SyntaxKind.Attribute) &&
                ((AttributeSyntax)node).GetText().ToString().Contains(pattern);
            #endregion
     
            #region Configuration
            internal static SyntaxTree TransformConfiguration(this SyntaxTree tree, string columnName, string oldPropertyName, string newPropertyName)
            {
                var node = tree.GetRoot();
                // try find comment
                var trivia = node.SelectCommentTriviaContaining(columnName);
                if (trivia.IsKind(SyntaxKind.None)) return tree;
     
                // uncomment
                var text = trivia.ToString();
                var code = text.Replace("//Property", "Property").Replace("x." + oldPropertyName, "x." + newPropertyName);
     
                var code2 = node.ToFullString().Replace(text, code);
                var newTree = CSharpSyntaxTree.ParseText(code2);
                return newTree;
            }
     
            internal static SyntaxTrivia SelectCommentTriviaContaining(this SyntaxNode node, string pattern) => node
                .DescendantTrivia()
                .Where(t => t.IsKind(SyntaxKind.SingleLineCommentTrivia))
                .OfType<SyntaxTrivia>()
                .Where(t => t.ToString().Contains(pattern))
                .SingleOrDefault();
            #endregion
        }
    }
    Fichier source :

    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
    [System.CodeDom.Compiler.GeneratedCode("EF.Reverse.POCO.Generator", "2.36.1.0")]
    public class KundeConfiguration : System.Data.Entity.ModelConfiguration.EntityTypeConfiguration<Kunde>
    {
        public KundeConfiguration()
            : this("dbo")
        {
        }
     
        public KundeConfiguration(string schema)
        {
            Property(x => x.Code).IsUnicode(false); // K_Code
            //Property(x => x.Vorname).IsOptional().IsUnicode(false); // K_Vorname
            //Property(x => x.Anderungsdatum).IsOptional(); // K_Anderungsdatum
        }
    }
    Fichier résultat :

    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
    [System.CodeDom.Compiler.GeneratedCode("EF.Reverse.POCO.Generator", "2.36.1.0")]
    public class KundeConfiguration : System.Data.Entity.ModelConfiguration.EntityTypeConfiguration<Kunde>
    {
        public KundeConfiguration()
            : this("dbo")
        {
        }
     
        public KundeConfiguration(string schema)
        {
            Property(x => x.Code).IsUnicode(false); // K_Code
            Property(x => x.FirstName).IsOptional().IsUnicode(false); // K_Vorname
            //Property(x => x.Anderungsdatum).IsOptional(); // K_Anderungsdatum
        }
    }
    Je verrai comment je peux faire pour le troisième. Il va aussi falloir que je m'accorde un peu de temps pour lire la doc et faire quelques recherches.

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

    Informations professionnelles :
    Activité : edi

    Informations forums :
    Inscription : Juin 2007
    Messages : 898
    Points : 1 915
    Points
    1 915
    Par défaut
    J'ai presque une solution pour le dernier fichier (je n'ai pas encore réussi à gérer correctement l'indentation) :

    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
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    using System.IO;
    using System.Linq;
    using Microsoft.CodeAnalysis;
    using Microsoft.CodeAnalysis.CSharp;
    using Microsoft.CodeAnalysis.CSharp.Syntax;
     
    namespace CodeTransform
    {
        class Program
        {
            static void Main(string[] args)
            {
                var columnName = "K_Vorname";
                var oldPropertyName = "Vorname";
                var newPropertyName = "FirstName";
                var tableName = "Customer";
                var tableDescription = "Customers";
                var newPropertyDescription = "First Name";
                TransformEntity("Kunde.cs", "Kunde.v2.cs", columnName, newPropertyName);
                TransformConfiguration("KundeConfiguration.cs", "KundeConfiguration.v2.cs", columnName, oldPropertyName, newPropertyName);
                TransformStore("KundeTableInformationStore.cs", "KundeTableInformationStore.v2.cs", tableName, tableDescription, oldPropertyName, newPropertyName, newPropertyDescription);
            }
     
            static void TransformEntity(string source, string destination, string columnName, string newPropertyName) =>
                source
                .Read()
                .Parse()
                .TransformEntity(columnName, newPropertyName)
                .ToString()
                .Write(destination);
     
            static void TransformConfiguration(string source, string destination, string columnName, string oldPropertyName, string newPropertyName) =>
                source
                .Read()
                .Parse()
                .TransformConfiguration(columnName, oldPropertyName, newPropertyName)
                .ToString()
                .Write(destination);
     
            static void TransformStore(string source, string destination, string tableName, string tableDescription, string oldPropertyName, string newPropertyName, string newPropertyDescription) =>
                source
                .Read()
                .Parse()
                .TransformStore(tableName, tableDescription, oldPropertyName, newPropertyName, newPropertyDescription)
                .ToString()
                .Write(destination);
        }
     
        static class CodeExtensions
        {
            internal static string Read(this string filePath) => File.ReadAllText(filePath);
            internal static SyntaxTree Parse(this string code) => CSharpSyntaxTree.ParseText(code);
            internal static void Write(this string code, string filePath) => File.WriteAllText(filePath, code);
     
            #region Entity
            internal static SyntaxTree TransformEntity(this SyntaxTree tree, string columnName, string newPropertyName) =>
                SyntaxFactory.SyntaxTree(tree.GetRoot().TransformProperty(columnName, newPropertyName));
     
            internal static SyntaxNode TransformProperty(this SyntaxNode node, string columnName, string newPropertyName)
            {
                var oldProp = node.SelectProperty(columnName);
                return node.ReplaceNode(oldProp, oldProp.Transform(newPropertyName));
            }
     
            internal static PropertyDeclarationSyntax SelectProperty(this SyntaxNode node, string columnName)
            {
                var att = node.SelectAttributeNodeContaining(columnName);
                var prop = att.Parent;
                return (PropertyDeclarationSyntax)prop;
            }
     
            internal static SyntaxNode Transform(this PropertyDeclarationSyntax prop, string newPropertyName) => prop
                   .RemoveNode(prop.SelectAttributeNodeContaining("NotMapped"), SyntaxRemoveOptions.KeepTrailingTrivia)
                   .WithIdentifier(SyntaxFactory.Identifier(newPropertyName));
     
            internal static SyntaxNode SelectAttributeNodeContaining(this SyntaxNode node, string pattern) =>
                node.RecognizeAttribute(pattern) ?
                node.Parent :
                node.ChildNodes().Select(n => n.SelectAttributeNodeContaining(pattern)).FirstOrDefault(n => n != null);
     
            internal static bool RecognizeAttribute(this SyntaxNode node, string pattern) =>
                node.IsKind(SyntaxKind.Attribute) &&
                ((AttributeSyntax)node).GetText().ToString().Contains(pattern);
            #endregion
     
            #region Configuration
            internal static SyntaxTree TransformConfiguration(this SyntaxTree tree, string columnName, string oldPropertyName, string newPropertyName)
            {
                var node = tree.GetRoot();
                // try find comment
                var trivia = node.SelectCommentTriviaContaining(columnName);
                if (trivia.IsKind(SyntaxKind.None)) return tree;
     
                // uncomment
                var text = trivia.ToString();
                var code = text.Replace("//Property", "Property").Replace("x." + oldPropertyName, "x." + newPropertyName);
     
                var code2 = node.ToFullString().Replace(text, code);
                var newTree = CSharpSyntaxTree.ParseText(code2);
                return newTree;
            }
     
            internal static SyntaxTrivia SelectCommentTriviaContaining(this SyntaxNode node, string pattern) => node
                .DescendantTrivia()
                .Where(t => t.IsKind(SyntaxKind.SingleLineCommentTrivia))
                .OfType<SyntaxTrivia>()
                .Where(t => t.ToString().Contains(pattern))
                .SingleOrDefault();
            #endregion
     
            #region Table
            internal static SyntaxTree TransformStore(this SyntaxTree tree, string tableName, string tableDescription, string oldPropertyName, string newPropertyName, string newPropertyDescription) =>
                SyntaxFactory.SyntaxTree(tree.GetRoot().TransformTable(tableName, tableDescription).TransformField(oldPropertyName, newPropertyName, newPropertyDescription));
     
            internal static SyntaxNode TransformTable(this SyntaxNode root, string tableName, string tableDescription)
            {
                var method = root.DescendantNodes()
                    .Where(n => n.IsKind(SyntaxKind.MethodDeclaration))
                    .Select(n => (MethodDeclarationSyntax)n)
                    .FirstOrDefault(m => m.Identifier.ValueText == "GetTableAndFields");
     
                var body = method.Body;
                var init = body.DescendantNodes()
                    .Where(n => n.IsKind(SyntaxKind.ObjectInitializerExpression))
                    .Select(n => (InitializerExpressionSyntax)n)
                    .SingleOrDefault();
     
                var newRoot = root.ReplaceNode(init, init.TransformAssignment("Name", tableName).TransformAssignment("Description", tableDescription));
                return newRoot;
            }
     
            internal static InitializerExpressionSyntax TransformAssignment(this InitializerExpressionSyntax node, string property, string value)
            {
                var assignments = node.ChildNodes().OfType<AssignmentExpressionSyntax>().ToArray();
                var assignment = assignments
                    .Where(a => a.Left.IsKind(SyntaxKind.IdentifierName))
                    .Where(a => ((IdentifierNameSyntax)a.Left).Identifier.ValueText == property)
                    .FirstOrDefault();
                var newAssignment = assignment.WithRight(SyntaxFactory.LiteralExpression(SyntaxKind.StringLiteralExpression, SyntaxFactory.Literal(value)));
                var newInit = node.ReplaceNode(assignment, newAssignment);
                return newInit;
            }
     
            internal static SyntaxNode TransformField(this SyntaxNode root, string oldPropertyName, string newPropertyName, string newPropertyDescription)
            {
                var method = root.DescendantNodes()
                    .Where(n => n.IsKind(SyntaxKind.MethodDeclaration))
                    .Select(n => (MethodDeclarationSyntax)n)
                    .FirstOrDefault(m => m.Identifier.ValueText == "GetFieldsOnly");
     
                var body = method.Body;
     
                var inits = body.DescendantNodes()
                    .Where(n => n.IsKind(SyntaxKind.ObjectInitializerExpression))
                    .Select(n => (InitializerExpressionSyntax)n)
                    .ToArray();
     
                var init = body.DescendantNodes()
                    .Where(n => n.IsKind(SyntaxKind.ObjectInitializerExpression))
                    .Select(n => (InitializerExpressionSyntax)n)
                    .FirstOrDefault(i => i.GetText().ToString().Contains(oldPropertyName));
     
                var newRoot = root.ReplaceNode(init,
                    init.TransformAssignment("Name", newPropertyName).TransformAssignment("Description", newPropertyDescription).AddMapped());
                return newRoot;
            }
     
            internal static InitializerExpressionSyntax AddMapped(this InitializerExpressionSyntax node)
            {
                var assignment = SyntaxFactory.AssignmentExpression(SyntaxKind.SimpleAssignmentExpression,
                        SyntaxFactory.IdentifierName("Mapped"),
                        SyntaxFactory.LiteralExpression(SyntaxKind.TrueLiteralExpression))
                    .NormalizeWhitespace();
                var newNode = node.AddExpressions(assignment);
                return newNode;
            }
            #endregion
        }
    }
    Fichier source :

    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
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Justification = "They are fields names")]
    public static class KundeTableInformationStore
    {
        /* CA1024 (Design) 
         * Use property if appropriate */
        public static ODataTableInformationModel TableAndFields
        {
            get { return GetTableAndFields(); }
        }
     
        private static ODataTableInformationModel GetTableAndFields()
        {
            ODataTableInformationModel result = new ODataTableInformationModel()
            {
                Name = "Kunde",
                InternalName = "KUNDE",
                Description = "Kunden",
                Prefix = "K",
                Key = "K_Code",
                Fields = GetFieldsOnly()
            };
     
     
            return result;
        }
     
        /* CA1024 (Design) 
         * Use property if appropriate */
        public static System.Collections.Generic.IEnumerable<ODataFieldInformationModel> Fields
        {
            get { return GetFieldsOnly(); }
        }
     
        private static System.Collections.Generic.IEnumerable<ODataFieldInformationModel> GetFieldsOnly()
        {
            return new System.Collections.Generic.List<ODataFieldInformationModel>()
                    {
                        new ODataFieldInformationModel()
                        {
                            TableName = "KUNDE",
                            Name = "Code",
                            InternalName = "K_Code",
                            Description = "Code",
                            DataType = "VARCHAR(17)",
                            Mapped = true
                        },
                        new ODataFieldInformationModel()
                        {
                            TableName = "KUNDE",
                            Name = "Vorname",
                            InternalName = "K_Vorname",
                            Description = "Vorname",
                            DataType = "VARCHAR(35)"
                        },
                        new ODataFieldInformationModel()
                        {
                            TableName = "KUNDE",
                            Name = "Änderungsdatum",
                            InternalName = "K_Anderungsdatum",
                            Description = "Änderungsdatum",
                            DataType = "DATE"
                        },
                };
         }
    }
    Fichier résultat :

    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
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Justification = "They are fields names")]
    public static class KundeTableInformationStore
    {
        /* CA1024 (Design) 
         * Use property if appropriate */
        public static ODataTableInformationModel TableAndFields
        {
            get { return GetTableAndFields(); }
        }
     
        private static ODataTableInformationModel GetTableAndFields()
        {
            ODataTableInformationModel result = new ODataTableInformationModel()
            {
                Name = "Customer",
                InternalName = "KUNDE",
                Description = "Customers",
                Prefix = "K",
                Key = "K_Code",
                Fields = GetFieldsOnly()
            };
     
     
            return result;
        }
     
        /* CA1024 (Design) 
         * Use property if appropriate */
        public static System.Collections.Generic.IEnumerable<ODataFieldInformationModel> Fields
        {
            get { return GetFieldsOnly(); }
        }
     
        private static System.Collections.Generic.IEnumerable<ODataFieldInformationModel> GetFieldsOnly()
        {
            return new System.Collections.Generic.List<ODataFieldInformationModel>()
                    {
                        new ODataFieldInformationModel()
                        {
                            TableName = "KUNDE",
                            Name = "Code",
                            InternalName = "K_Code",
                            Description = "Code",
                            DataType = "VARCHAR(17)",
                            Mapped = true
                        },
                        new ODataFieldInformationModel()
                        {
                            TableName = "KUNDE",
                            Name = "FirstName",
                            InternalName = "K_Vorname",
                            Description = "First Name",
                            DataType = "VARCHAR(35)"
    ,Mapped = true                    },
                        new ODataFieldInformationModel()
                        {
                            TableName = "KUNDE",
                            Name = "Änderungsdatum",
                            InternalName = "K_Anderungsdatum",
                            Description = "Änderungsdatum",
                            DataType = "DATE"
                        },
                };
         }
    }

  9. #9
    Expert confirmé
    Avatar de popo
    Homme Profil pro
    Analyste programmeur Delphi / C#
    Inscrit en
    Mars 2005
    Messages
    2 672
    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 : 2 672
    Points : 5 253
    Points
    5 253
    Par défaut
    Merci, ça fonctionne parfaitement dans les cas que j'ai essayé.
    Tu m'enlèves vraiment une épine du pied

    Il ne me reste plus qu'à mettre de l'automatisation autour.

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

    Informations professionnelles :
    Activité : edi

    Informations forums :
    Inscription : Juin 2007
    Messages : 898
    Points : 1 915
    Points
    1 915
    Par défaut
    C'est cool que ça t'ai été utile. Je n'étais pas tout à fait satisfait à cause du problème d'indentation de la dernière partie, mais au moins ça ne gêne pas la compilation. Par contre Roslyn permet différents niveaux d'abstraction, notamment d'aborder les chose au niveau du workspace pour faire des changements de fichiers liés entre eux d'un point de vue sémantique. Il est même possible de faire une extension Visual Studio pour repérer l'ensemble des fichiers concernés.

  11. #11
    Expert confirmé
    Avatar de popo
    Homme Profil pro
    Analyste programmeur Delphi / C#
    Inscrit en
    Mars 2005
    Messages
    2 672
    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 : 2 672
    Points : 5 253
    Points
    5 253
    Par défaut
    Je te confirme que l'indentation n'est vraiment pas un problème.
    Surtout que Visual Studio dispose d'outil pour refaire cette indentation correctement.

    L'extension Visual Studio, c'est un peu trop pour mon besoin.
    J'imaginais une juste IHM pour sélectionner un fichier Excel (un par table et dont le nom serait significatif) et une simple boucle pour passer sur toutes les colonnes dont j'ai besoin.
    Mais je garde ton idée sous le coude pour ma culture personnelle.
    Merci.

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

Discussions similaires

  1. [WD19] Modifier police et taille fichier excel par programmation
    Par remi82 dans le forum WinDev
    Réponses: 12
    Dernier message: 27/08/2014, 15h12
  2. Rechercher un/des fichier(s) par sa taille
    Par maxoudu328 dans le forum Delphi
    Réponses: 4
    Dernier message: 13/11/2006, 16h27
  3. Réponses: 11
    Dernier message: 02/11/2006, 16h50
  4. Réponses: 6
    Dernier message: 14/04/2006, 16h35
  5. Noms des fichiers téléchargés par wget
    Par benj63 dans le forum Linux
    Réponses: 2
    Dernier message: 22/02/2006, 11h54

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