Dans ce post nous allons utiliser les services proposés par l’IDE Visual Studio (automation) pour créer une classe c# et ajouter ce fichier à un projet.

Objet DTE2

Pour pouvoir commencer à utiliser l’automation, il faut une instance d’objet DTE2. DTE2 représente l’objet ‘racine’, en d’autre terme l’application visual studio. Lorsque l’on crée une extension dans Visual Studio (VSIX), il est très facile de récupérer cette instance via la classe package générée, correspondant à votre extension :

public sealed class BlogAutomationVsixPackage : Package

et pour récupérer l’instance :

DTE2 dte2 = BlogAutomationVsixPackage
                         .GetGlobalService(typeof(DTE)) as DTE2;

Dans le cas d’une application “classique” (application console par ex), on récupère l’instance DTE2 du Visual Studio actif comme ceci :

EnvDTE80.DTE2 dte2;
dte2 = (EnvDTE80.DTE2)System.Runtime.InteropServices.Marshal.
        GetActiveObject("VisualStudio.DTE.11.0");

NOTE : pour utiliser les objets d’automation, vous devez ajouter en référence les assemblies suivantes : EnvDTE, EnvDTE80. Ces assemblies sont automatiquement référencées dans un projet VSIX.

Objet Project

L’objet EnvDte. Projet sera notre point d’entrée pour ajouter notre fichier. Nous pouvons récupérer le projet qui nous intéresse (projet portant le nom “Lib&rdquo 😉 de la façon suivante :

IEnumerator projectEnumerator = dte2.Solution.Projects.GetEnumerator();
 Project libProject = null;
 while (projectEnumerator.MoveNext())
 {
         Project proj = projectEnumerator.Current as Project;
         if (proj.Name == "Lib")
         {
               libProject = proj;
               break;
          }
  } 

Note : On remarque que notre objet DTE2 a une propriété ‘Solution’, contenant l’ensemble des projets, sur lequel il est également possible d’appeler des opérations d’ajout ou de suppression de fichier par exemple (item de solution).

Ajout du fichier dans le projet

Dans un premier temps il nous faut le path du template des fichiers de type ‘classe c#’ :

string templatePath = 
((Solution2)dte2.Solution).GetProjectItemTemplate("CodeFile", "csharp");

Et on ajoute le fichier à la collection d’items de notre projet :

libProject.ProjectItems.
                   AddFromTemplate(templatePath, "GeneratedFile.cs");

Objet FileCodeModel : génération du code

Voilà notre fichier a maintenant été ajouté à notre projet. Nous allons pouvoir générer le code via l’objet ProjectItem correspondant à ce fichier :

ProjectItem csFile = libProject.ProjectItems.Item("GeneratedFile.cs"); 

Les objets ProjectItem ont une propriété FileCodeModel qui est le point d’entrée pour l’ajout de code dans notre fichier. Dans l’ordre, nous ajoutons le namespace, la classe, le constructeur, une méthode, et une variable :

((FileCodeModel2)csFile.FileCodeModel).AddImport("System");
CodeNamespace nSpace = csFile.FileCodeModel.AddNamespace("Lib");
CodeClass codeClass = nSpace.AddClass
(
     "GeneratedFile", 
      null, 
      null, null, 
      vsCMAccess.vsCMAccessPublic
);
codeClass.AddFunction(
    "GeneratedFile", 
    vsCMFunction.vsCMFunctionConstructor, 
    null, 1, 
    vsCMAccess.vsCMAccessPublic
);
codeClass.AddFunction
(
   "MyFunction", 
    vsCMFunction.vsCMFunctionFunction, 
   "void", 2, 
    vsCMAccess.vsCMAccessPublic
);
((CodeClass2)codeClass).AddVariable("_myProperty", "string", null);

Et voilà le résultat !

Ne ratez plus aucunes actualités avec la newsletter mensuelle de SoftFluent