|
1 | 1 | # Automate Project Information |
2 | | - ADD Content here |
| 2 | +In this section we will be using CodeFactory to get information about a project hosted in a Visul Studio solution and displaying it. |
| 3 | +This guidiance is expected to accomplish the following. |
| 4 | + |
| 5 | + - How to format a CodeFactory command |
| 6 | + - How to consume data from the CodeFactory Framework |
| 7 | + - How to create a user interface and display data from CodeFactory |
| 8 | + |
| 9 | +## Assumptions |
| 10 | +It is assumsed you have completed the guidance Creating a Project. If you have not done that yet please click the link below and complete the first part before continuing. |
| 11 | + |
| 12 | +[Creating A Project](CreateProject.md) |
| 13 | + |
| 14 | + |
| 15 | +## Goals |
| 16 | +In this section we are going to create a project command that will display information about the project itself. |
| 17 | +The following information will be displayed about the project itself. |
| 18 | + |
| 19 | +- Project Name |
| 20 | +- Number of project files |
| 21 | +- Number of project references |
| 22 | + |
| 23 | +## CodeFactory Command Information |
| 24 | +CodeFactory commands are raised directly by Visual Studio through the CodeFactory Framework. |
| 25 | + |
| 26 | +### Command Title |
| 27 | +All CodeFactory commands have a title that is displayed in Visual Studio context menus. The field commandTitle that is hosted in the target command class is where the title for the command is set. |
| 28 | + |
| 29 | +### Command Description |
| 30 | +All CodeFactory commands have a description that is used on summary screens to explain what the command is for. The field commandDescription this is hosted in the target command class is where the description is set. |
| 31 | + |
| 32 | +### Enable Command |
| 33 | +Every command has an over ride for the method EnableCommandAsync and it provides the Datamodel for the target solution explorer element it represents. |
| 34 | +The CodeFactory framework calls this method to determine if this command should be displayed to the user in Visual Studio. |
| 35 | +There are times that command should not be displayed. |
| 36 | +For example If we want to add missing members to a class. |
| 37 | +If no members are missing we would not show the command. |
| 38 | +With this in mind, the enable command allows you to use the data in the data model to determine if a command should be enabled for usage. |
| 39 | + |
| 40 | +The return from this method is true or false. If set to true the command will be displayed on the context menu. |
| 41 | +If set to false it will not show up on the context menu and no further execution will be performed. |
| 42 | + |
| 43 | +### Execute Command |
| 44 | +Once a command has been enabled and the user selected the command from the context menu, CodeFactory will execute the command. |
| 45 | +CodeFactory will call the Overridden ExecuteCommandAsync implemented in your command class. Like with the enable command it will provide the current data for the target solution explorer element. |
| 46 | +This is where CodeFactory will execute your custom automation. |
| 47 | + |
| 48 | +# Command Implementation |
| 49 | +In this section we will implement all the logic that will display the project information. |
| 50 | +This has been broken down in to sub sections to provide greater clarification of each set of steps. |
| 51 | + |
| 52 | +## Format the Command |
| 53 | +Before we begin the automation logic we need to format the command so it is ready for usage by staff. |
| 54 | +The following steps will be taken to format the command. |
| 55 | + |
| 56 | +### Update the Command Title and Description |
| 57 | +First we need to set the title and the description of the command so they display correctly in Visual Studio. |
| 58 | + |
| 59 | +The following steps will be performed in the ProjectInformationCommand.cs code file. |
| 60 | + |
| 61 | +1. We update the command title to Show Project Information. |
| 62 | + |
| 63 | +From: |
| 64 | +``` |
| 65 | +private static readonly string commandTitle = "Replace with command title to be displayed in context menu"; |
| 66 | +``` |
| 67 | + |
| 68 | +To: |
| 69 | +``` |
| 70 | +private static readonly string commandTitle = "Show Project Information"; |
| 71 | +``` |
| 72 | +___ |
| 73 | +2. We update the command description to Displays basic information about the project. |
| 74 | + |
| 75 | +From: |
| 76 | +``` |
| 77 | +private static readonly string commandDescription = "Replace with description of what this command does"; |
| 78 | +``` |
| 79 | + |
| 80 | +To: |
| 81 | +``` |
| 82 | +private static readonly string commandDescription = "Displays basic information about the project"; |
| 83 | +``` |
| 84 | +____ |
| 85 | +3. Once updated should look like this. |
| 86 | + |
| 87 | + |
| 88 | +___ |
| 89 | + |
| 90 | +### Setup then Enable Command |
| 91 | +Since we are displaying information about a project there are no extended conditions to validate we will just make sure we received a loaded data model from CodeFactory. |
| 92 | + |
| 93 | +1. CodeFactory already gives us a fully templated out method. So we will replace the to do with our enable logic. The provided method is shown below. |
| 94 | + |
| 95 | + |
| 96 | +___ |
| 97 | +2. We will replace the TODO line with a check to make sure the data model loaded. |
| 98 | +When a data model is loaded is has a property to determine if the data model was loaded or if it could not be loaded due to errors. |
| 99 | +By default the method has a isEnabled variable aready created so we will check to the model is loaded and set isEnabled based on if the model is loaded. |
| 100 | + |
| 101 | +From: |
| 102 | +``` |
| 103 | +//TODO: Add logic to determine if this command is enabled. |
| 104 | +``` |
| 105 | + |
| 106 | +To: |
| 107 | +``` |
| 108 | +isEnabled = result.IsLoaded; |
| 109 | +``` |
| 110 | +___ |
| 111 | +3. One the code updates are completed should look like this. |
| 112 | + |
| 113 | + |
| 114 | +___ |
| 115 | +### Testing the Formatted Command |
| 116 | +Before we dive into the logic lets go ahead and test to make sure our command formatting is correct. So we are going to debug our automation we have created so far. |
| 117 | + |
| 118 | +1. Click Start Debugging this will be the play button icon on your tool bar with star next to it. |
| 119 | + |
| 120 | + |
| 121 | + |
| 122 | +You will notice that will start a new instance of Visual Studio. |
| 123 | +This is by design CodeFactory automation runs inside of Visual Studio so we debug it from another instance. |
| 124 | +___ |
| 125 | + |
| 126 | +2. From the What would you like to do? window click Create a new project |
| 127 | + |
| 128 | + |
| 129 | +Or you can start the same process if you dont use the start up window. |
| 130 | + - Click the File menu |
| 131 | + - From the context menu select New |
| 132 | + - From the sub context menu select Project |
| 133 | + |
| 134 | + |
| 135 | +___ |
| 136 | +3. From the Create a new project dialog do the following. |
| 137 | + |
| 138 | + |
| 139 | + |
| 140 | + - In the search box type standard |
| 141 | + - Select C# Class Library (.NET Standard) |
| 142 | + - Click the Next button |
| 143 | +___ |
| 144 | +4. From the Configure your new project dialog do the following. |
| 145 | + |
| 146 | + |
| 147 | + |
| 148 | + - In the Project name text box enter CodeFactoryTesting |
| 149 | + - Click Create button |
| 150 | +___ |
| 151 | +5. Once the project and solution have been created they will load. |
| 152 | +We will reuse this project and solution for all further testing as we complete the automation for this project. |
| 153 | +To test the CodeFactory command we do the following. |
| 154 | + |
| 155 | + |
| 156 | + |
| 157 | +- Right click on the Project node in solution explorer |
| 158 | +- From the context menu at the bottom you will see the Show Project Information command. |
| 159 | +- Testing complete we know the command is running. |
| 160 | +- Close the debugger instance of Visual Studio |
| 161 | +___ |
| 162 | + |
| 163 | +## Gather Project Information |
| 164 | +Now that the project command has been formatted we are ready to begin the automation logic. |
| 165 | +We need to get the following information and prepair it to be displayed to the user. |
| 166 | + |
| 167 | + - Project Name - The name of the project itself |
| 168 | + - Number of References - The count of how many references are tied to this project |
| 169 | + - Number of files - The number of files that are hosted in this project. |
| 170 | + |
| 171 | +This logic will be hosted directly in the execute command. |
| 172 | +This gets called by the CodeFactory framework as soon as the command is selected from the context menu by a developer using our automation. |
| 173 | + |
| 174 | +When we created the project command class it automatically added the ExecuteCommandAsync method. Which looks like this. |
| 175 | + |
| 176 | + |
| 177 | + |
| 178 | +The following steps will be taken to add the project information logic to the ExecuteCommandAsync Method. |
| 179 | + |
| 180 | +1. We will replace the TODO block with a bounds check to make sure we got a project model that was loaded. |
| 181 | +If the model is not loaded will use a Messagebox to display a message explaining what happened. |
| 182 | +From: |
| 183 | +``` |
| 184 | +//TODO: Add command logic |
| 185 | +``` |
| 186 | +To: |
| 187 | +``` |
| 188 | +if (!result.IsLoaded) |
| 189 | +{ |
| 190 | + MessageBox.Show("Could not access the project information. Cannot display the project information", |
| 191 | + "No Model Data", MessageBoxButton.OK, MessageBoxImage.Exclamation); |
| 192 | + return; |
| 193 | +} |
| 194 | +``` |
| 195 | +Updated code will look like this. |
| 196 | + |
| 197 | +___ |
| 198 | +2. After our bounds check we will add the three variables that will be used to store the project information to be displayed. |
| 199 | + |
| 200 | +``` |
| 201 | +string projectName = null; |
| 202 | +int projectReferences = 0; |
| 203 | +int projectFiles = 0; |
| 204 | +``` |
| 205 | +Updated code will look like this. |
| 206 | + |
| 207 | +___ |
| 208 | +3. Will capture the project name from the returned data model by entering the following. |
| 209 | + |
| 210 | +``` |
| 211 | +projectName = result.Name; |
| 212 | +``` |
| 213 | +Updated code will look like this. |
| 214 | + |
| 215 | +___ |
| 216 | +4. Next we will need to get the project references that are assigned to the project. |
| 217 | +This is done through a CodeFactory API call. Most CodeFactory API calls that talk to Visual Studio are done using an async call. |
| 218 | +This improves Visual Studio performance by running the tasks in the background when possible. |
| 219 | +We get the references and add them to a var parameter to hold the references. |
| 220 | +Then we will get the count of all references and add it to our projectReferences variable. |
| 221 | + |
| 222 | +``` |
| 223 | +var references = await result.GetProjectReferencesAsync(); |
| 224 | +projectReferences = references.Count; |
| 225 | +``` |
| 226 | +Updated code will look like this. |
| 227 | + |
| 228 | +___ |
| 229 | +5. The final data needed from the project is the number of files that are hosted by the project. |
| 230 | +Like with project references we need to make a CodeFactory API to get the real time data for each file and folder that hosted in the project. |
| 231 | +This API call can access just the project root level or access all nested levels under folders. |
| 232 | +We are going to tell it to get all nested levels. |
| 233 | + |
| 234 | +Since there are multiple different data models that represent Visual Studio data. |
| 235 | +The data that is returned as an inherited data type of all Visual Studio data called a VsModel. |
| 236 | +The inherited base class tells you what type of model is being represented. |
| 237 | +You can then cast the model to the target type and use it. |
| 238 | + |
| 239 | +A call is made to get all children of the project and stored in a var named projectChildren. |
| 240 | +Then using a where clause on the projectChildren we select all models that are a document and store it in a var named files. |
| 241 | +Finally we set our projectFiles variable with the count of the found files. |
| 242 | + |
| 243 | +``` |
| 244 | +var projectChildren = await result.GetChildrenAsync(true); |
| 245 | +var files = projectChildren.Where(m => m.ModelType == VisualStudioModelType.Document); |
| 246 | +projectFiles = files.Count(); |
| 247 | +``` |
| 248 | +Updated code will look like this. |
| 249 | + |
| 250 | + |
| 251 | +## Build Visual Studio Dialog |
| 252 | + |
| 253 | + |
| 254 | +## Create and Display Dialog |
| 255 | + |
3 | 256 |
|
4 | 257 | ## Return to Guidance |
5 | 258 | This concludes the complete training for how to create a CodeFactory project. The link below will take you back to the guidance page. |
|
0 commit comments