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?