Today I wrote a wrapper to be in control when unit testing some code that uses System.Random. After completing the task, which is mindless automation, I decided to create a T4 template for it. After completing the few lines in a separate solution I copied it over only to find some ugly error being generated.
After some oldschool write-debug-to-output, I found the issue to be the dots in the namespace. Come on Microsoft, everybody uses dots in their namespace. The best practice is something like Company.Product.Library …
The solution is to avoid dots (joke) or to query one level deeper to find the namespace. Codesample below.
<#@ template debug="true" hostSpecific="true" #> <#@ output extension=".cs" #> <#@ Assembly Name="System.Core" #> <#@ assembly name="EnvDTE" #> <#@ import namespace="System" #> <#@ import namespace="System.Linq" #> <#@ import namespace="EnvDTE" #> // ---------------------------- // Generated on <#= System.DateTime.Now.ToString() #> // any changes will be lost the next time this file is generated // This file contains a list of all classes in the project // ---------------------------- <# var visualStudio = (Host as IServiceProvider).GetService(typeof(EnvDTE.DTE)) as EnvDTE.DTE; var project = visualStudio.Solution.FindProjectItem(Host.TemplateFile).ContainingProject as EnvDTE.Project; var rootNamespace = (string)project.Properties.Item("RootNamespace").Value; // chop into parts between the dots var dots = rootNamespace.Split('.'); var codenamespace = project.CodeModel.CodeElements.OfType<EnvDTE.CodeNamespace>().Where(cn => cn.FullName == dots[0]).First(); // query with an extra part of the namespace (Company, Company.Product, Company.Product.Library) for(int i = 1; i < dots.Length; i++) { var filter = string.Join(".", dots.Take(i + 1)); codenamespace = codenamespace.Members.OfType<EnvDTE.CodeNamespace>().Where(cn => cn.FullName == filter).First(); } if (codenamespace != null) { var classes = codenamespace.Members.OfType<EnvDTE.CodeClass>(); foreach(var classItem in classes) WriteLine("// {0}", classItem.FullName); } else { WriteLine("// namespace not found"); } #>
Check back for future updates on generating design patterns as I am building myself a library.
Further reading:
- Carlos Quintero blog (Microsoft MVP)
- Tangible T4 editor (must install)
- MSDN Automation and Extensibility Reference_
[edit September 9, 2013]
Codesample optimization with namespace split on dots and query every part: Company, Company.Product, Company.Product.Library
[/edit]
Any final solution with full source code samples using Unit Testing C# and EnvDTE ? for VS 2008, VS2010 and VS 2012 ?
What issue with above code do you encounter?