Permalink
Find file
Fetching contributors…
Cannot retrieve contributors at this time
executable file 190 lines (163 sloc) 5.37 KB
<#@ template hostspecific="true" language="C#" #>
<#@ assembly name="EnvDte" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.Linq" #>
<#
var namespaceOfBuilders = "Tests";
var project = GetProjectContainingFile("Dtos.cs");
var dtoTypes = GetClassesOf(project).Where(c => c.Name.EndsWith("Dto")).ToList();
#>
using System;
using System.Linq;
namespace <#=namespaceOfBuilders #>
{
public class Build
{
<#
PushIndent("\t");
foreach(var dtoType in dtoTypes)
{
PushIndent("\t");
#>public static <#= dtoType.Name #>Builder <#= dtoType.Name #> { get { return new <#= dtoType.Name #>Builder(); } }
<#
PopIndent();
}
PopIndent();
#>
}
public abstract class Builder<TDto>
{
protected TDto dto;
public Builder()
{
dto = Activator.CreateInstance<TDto>();
Defaults();
}
protected virtual void Defaults() {}
public TDto Build()
{
return dto;
}
}
<#
foreach(var dtoType in dtoTypes)
{
#>
public partial class <#= dtoType.Name #>Builder : Builder<<#= dtoType.Namespace.Name #>.<#= dtoType.Name #>>
{
<#foreach(var property in FindProperties(dtoType.Members))
{#> public <#= dtoType.Name #>Builder With<#=property.Name #>(<#=property.Type.AsFullName #> <#=property.Name.ToLower() #>)
{
dto.<#=property.Name #> = <#=property.Name.ToLower() #>;
return this;
}
<#
// If property is type of DTO then let's add With-method supporting nested building.
if(dtoTypes.Any(dt => dt.Namespace.Name + "." + dt.Name == property.Type.AsFullName))
{
var builderType = property.Type.AsFullName.Substring(property.Type.AsFullName.LastIndexOf('.') + 1);
#>
public <#= dtoType.Name #>Builder With<#=property.Name #>(Action<<#=builderType #>Builder> <#=property.Name.ToLower() #>Builder)
{
var b = new <#=builderType #>Builder();
<#=property.Name.ToLower() #>Builder.Invoke(b);
dto.<#=property.Name #> = b.Build();
return this;
}
<#
} /* if */
#><#
// If property is List type then let's add With-method with params support
if(property.Type.AsFullName.StartsWith("System.Collections.Generic.List"))
{
#>
public <#= dtoType.Name #>Builder With<#=property.Name #>(params <#=GetListedType(property) #>[] <#=property.Name.ToLower() #>)
{
dto.<#=property.Name #> = <#=property.Name.ToLower() #>.ToList();
return this;
}
<#
} /* if */
// If property is List type then let's add With-method with params support
if(property.Type.AsFullName.StartsWith("System.Collections.Generic.List"))
{
var builderType = GetListedType(property).Substring(GetListedType(property).LastIndexOf('.') + 1);
#>
public <#= dtoType.Name #>Builder With<#=property.Name #>(params Action<<#=builderType #>Builder>[] builders)
{
var <#=property.Name.ToLower() #> = new <#=property.Type.AsFullName #>();
foreach(var builder in builders)
{
var b = new <#=builderType #>Builder();
builder.Invoke(b);
<#=property.Name.ToLower() #>.Add(b.Build());
}
dto.<#=property.Name #> = <#=property.Name.ToLower() #>;
return this;
}
<#
} /* if */
} /* foreach */#>
}
<#}#>}
<#+
public List<EnvDTE.ProjectItem> GetProjectItemsRecursively(EnvDTE.ProjectItems items)
{
var ret = new List<EnvDTE.ProjectItem>();
if (items == null) return ret;
foreach(EnvDTE.ProjectItem item in items)
{
ret.Add(item);
ret.AddRange(GetProjectItemsRecursively(item.ProjectItems));
}
return ret;
}
public string GetListedType(EnvDTE.CodeProperty property)
{
return property.Type.AsFullName.Replace("System.Collections.Generic.List<", "").Replace(">","");
}
public EnvDTE.Project GetProjectContainingFile(string filename)
{
var visualStudio = (this.Host as IServiceProvider).GetService(typeof(EnvDTE.DTE)) as EnvDTE.DTE;
return visualStudio.Solution.FindProjectItem(filename).ContainingProject as EnvDTE.Project;
}
public List<EnvDTE.CodeClass> GetClassesOf(EnvDTE.Project project)
{
var items = GetProjectItemsRecursively(project.ProjectItems);
var classes = new List<EnvDTE.CodeClass>();
foreach(var item in items)
{
if(item.FileCodeModel != null)
{
foreach (EnvDTE.CodeElement element in item.FileCodeModel.CodeElements)
{
if (element is EnvDTE.CodeNamespace)
{
EnvDTE.CodeNamespace ns = (EnvDTE.CodeNamespace)element;
foreach (EnvDTE.CodeElement elem in ns.Members)
{
if (elem is EnvDTE.CodeClass)
{
classes.Add(elem as EnvDTE.CodeClass);
}
}
}
}
}
}
return classes;
}
public List<EnvDTE.CodeProperty> FindProperties(EnvDTE.CodeElements elements)
{
List<EnvDTE.CodeProperty> properties = new List<EnvDTE.CodeProperty>();
foreach (EnvDTE.CodeElement element in elements)
{
EnvDTE.CodeProperty p = element as EnvDTE.CodeProperty;
if (p != null)
properties.Add(p);
}
return properties;
}
#>