Reading Input
So far, I've just assumed that I've retrieved the inputs to the process: the names of the connections string in the app.config or web.config file. In this section, I look at retrieving that input and integrating it into the solution. I've kept the code for this case study purposely simple to concentrate on the structure of a code-generation solution. For a case study that generates more complex code, see Chapter 10.
Processing the Configuration File
The connection strings are kept in the configuration file for the application, so my first step is to retrieve either the web.config file (for ASP.NET projects) or app.config file (for all other project types). Rather than check the project type, I use the ProjectItems collection to try and retrieve the app.config file; if I don't find it, I try to retrieve the web.config file. If neither is found, there are no connection strings to generate so I display a status message and exit.
Because failing to find an item in the ProjectItems collection raises an error, I use a try...catch block to determine if the configuration files are found:
ProjectItem cfg; try { cfg = prj.ProjectItems.Item("web.config"); } catch { try { cfg = prj.ProjectItems.Item("app.config"); } catch { if (prj == null) { applicationObject.DTE.StatusBar.Text = "No configuration file."; return; } } }
Once I've found the configuration file, the next step is to read it. The Properties collection for a Project item includes the FullPath to the item. Using that value, I can load the configuration file into an XMLDocument, as this code does:
System.Xml.XmlDocument dom; dom = new System.Xml.XmlDocument(); dom.Load(@cfg.Properties.Item("FullPath").Value.ToString());
Adding Property Code
With the document loaded, the next step is to loop through the children of the connectionStrings element. For each child element, I retrieve the name attribute from the element and use that to create the property:
System.Xml.XmlNode ndCons = dom.SelectSingleNode("//connectionStrings"); foreach (System.Xml.XmlNode ndCon in ndCons) { string PropertyName = ndCon.Attributes["name"].Value; CodeProperty cp; cp = cc.AddProperty(PropertyName, null, vsCMTypeRef.vsCMTypeRefString, -1, vsCMAccess.vsCMAccessPublic, null); cp.Getter.IsShared = true; EditPoint epGetter = cp.Getter.GetStartPoint( vsCMPart.vsCMPartBody).CreateEditPoint(); epGetter.Delete(cp.Getter.GetEndPoint(vsCMPart.vsCMPartBody)); epGetter.Insert("return " + "System.Web.Configuration.WebConfigurationManager." + "ConnectionStrings[\""+ PropertyName + "\"].ConnectionString;"); }
For a non-ASP application, the last line of code looks like this:
epGetter.Insert("return ConfigurationManager.ConnectionStrings[ \"" + PropertyName + "\"].ConnectionString;");