我试图从命令行自动化我的构建。不幸的是,我的项目并不打算从一开始就被自动化,现在我正在努力与T4模板。TextTransform无效的转换错误
发现了几个错误后(this和this)尝试使用改造T4模板的MSBuild当我决定从我的项目的根目录找到所有的* .TT文件,并通过应用TextTransform给他们,一个一。
但是...其中一些有点问题。当那些运行TextTransform我收到以下消息:
C:\Specifications.tt(0,0) : error : Running transformation: System.InvalidCastException: Cannot convert 'Microsoft.VisualStudio.TextTemplating.CommandLine.CommandLineHost' into 'System.IServiceProvider'. en Microsoft.VisualStudio.TextTemplating7ea01e60423f49d2871739be33c0c810.GeneratedTextTransformation.GetProject() in Microsoft.VisualStudio.TextTemplating7ea01e60423f49d2871739be33c0c810.GeneratedTextTransformation.FindClasses(String nameSpace, String className, String baseClassName) in Microsoft.VisualStudio.TextTemplating7ea01e60423f49d2871739be33c0c810.GeneratedTextTransformation.TransformText()
打开.TT和寻找的IServiceProvider或CommandLineHost,我发现这两种方法:
private Project GetProject()
{
IServiceProvider serviceProvider = (IServiceProvider)this.Host;
DTE dte = serviceProvider.GetService(typeof(DTE)) as DTE;
// Get DTE
//var dte = (DTE)TransformationContext.Current.GetService(typeof(DTE));
// Get ProjectItem representing the template file
ProjectItem projectItem = dte.Solution.FindProjectItem(this.Host.TemplateFile);
// Get the Project of the template file
Project project = projectItem.ContainingProject;
return project;
}
private string GetDefaultNamespace()
{
IServiceProvider serviceProvider = (IServiceProvider)this.Host;
DTE dte = serviceProvider.GetService(typeof(DTE)) as DTE;
// Get DTE
//var dte = (DTE)TransformationContext.Current.GetService(typeof(DTE));
// Get ProjectItem representing the template file
ProjectItem projectItem = dte.Solution.FindProjectItem(this.Host.TemplateFile);
// Get the Project of the template file
Project project = projectItem.ContainingProject;
var vsSolution = (IVsSolution)serviceProvider.GetService(typeof(SVsSolution));
IVsHierarchy vsHierarchy;
ErrorHandler.ThrowOnFailure(vsSolution.GetProjectOfUniqueName(project.FullName, out vsHierarchy));
uint projectItemId;
ErrorHandler.ThrowOnFailure(vsHierarchy.ParseCanonicalName(projectItem.FileNames[1], out projectItemId));
object defaultNamespace;
ErrorHandler.ThrowOnFailure(vsHierarchy.GetProperty(projectItemId, (int)VsHierarchyPropID.DefaultNamespace, out defaultNamespace));
return ((string)defaultNamespace);
}
是否有可能解决此不知何故?更改.tt代码,使用替代方法...
我只是想从命令行自动化我的构建!
UPDATE 以下是模板的全部内容:
<#@ template language="C#" debug="false" hostspecific="true"#>
<#@ assembly name="EnvDTE" #>
<#@ assembly name="Microsoft.VisualStudio.Shell.11.0" #>
<#@ assembly name="Microsoft.VisualStudio.Shell.Interop" #>
<#@ import namespace="EnvDTE" #>
<#@ import namespace="Microsoft.VisualStudio.Shell" #>
<#@ import namespace="Microsoft.VisualStudio.Shell.Interop" #>
<#@ include file="EF.Utility.CS.ttinclude"#>
<#@ output extension="/"#>
<#
CodeGenerationTools code = new CodeGenerationTools(this);
MetadataLoader loader = new MetadataLoader(this);
CodeRegion region = new CodeRegion(this, 1);
MetadataTools ef = new MetadataTools(this);
string namespaceName = code.VsNamespaceSuggestion();// @"ArcNet.Piloto.Domain.Repositories";
string filenameSuffix = "Repository.cs";
// include additional using statements here
List<string> usingList = new List<string>(){
"IDB.MW.Domain.Entities",
"EverNext.Domain.Contracts.Repositories",
"System.ServiceModel",
"System.CodeDom.Compiler",
"EverNext.Domain.Contracts.Model"
// ,"other namespace"
};
////////////////////////////////////////////////////////////////////////////// Don't edit from here
EntityFrameworkTemplateFileManager fileManager = EntityFrameworkTemplateFileManager.Create(this);
// Write out support code to primary template output file
WriteHeader(fileManager, usingList.ToArray());
BeginNamespace(namespaceName, code);
EndNamespace(namespaceName);
// Emit Entity Types
foreach (var classes in FindClasses("IDB.MW.Domain.Entities", "", "BaseEntity").Where(c=>c.ImplementedInterfaces.OfType<CodeInterface>()
.Any(d=>d.Name.Equals("IAggregateRoot"))))
{
fileManager.StartNewFile(classes.Name + filenameSuffix);
BeginNamespace(namespaceName, code);
#>
[ServiceContract]
<#="public"#> <#=code.SpaceAfter(classes.IsAbstract ? "abstract" : string.Empty)#>partial interface I<#=classes.Name#>Repository : IEntityRepository<<#=classes.Name#>>,IAggregateRoot
{
}
<#
EndNamespace(namespaceName);
}
//
//if (!VerifyTypesAreCaseInsensitiveUnique(ItemCollection))
//{
//return "";
//}
fileManager.Process();
#>
<#+
void WriteHeader(EntityFrameworkTemplateFileManager fileManager, params string[] extraUsings)
{
fileManager.StartHeader();
#>
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated from a template.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
using System;
using System.Linq;
<#=String.Join(String.Empty, extraUsings.Select(u => "using " + u + ";" + Environment.NewLine).ToArray())#>
<#+
fileManager.EndBlock();
}
void BeginNamespace(string namespaceName, CodeGenerationTools code)
{
CodeRegion region = new CodeRegion(this);
if (!String.IsNullOrEmpty(namespaceName))
{
#>
namespace <#=code.EscapeNamespace(namespaceName)#>
{
<#+
PushIndent(CodeRegion.GetIndent(1));
}
}
void EndNamespace(string namespaceName)
{
if (!String.IsNullOrEmpty(namespaceName))
{
PopIndent();
#>
}
<#+
}
}
bool VerifyTypesAreCaseInsensitiveUnique(EdmItemCollection itemCollection)
{
Dictionary<string, bool> alreadySeen = new Dictionary<string, bool>(StringComparer.OrdinalIgnoreCase);
foreach(StructuralType type in itemCollection.GetItems<StructuralType>())
{
if (!(type is EntityType || type is ComplexType))
{
continue;
}
if (alreadySeen.ContainsKey(type.FullName))
{
Error(String.Format(CultureInfo.CurrentCulture, "This template does not support types that differ only by case, the types {0} are not supported", type.FullName));
return false;
}
else
{
alreadySeen.Add(type.FullName, true);
}
}
return true;
}
private System.Collections.Generic.List<CodeClass> FindClasses(string nameSpace, string className, string baseClassName)
{
System.Collections.Generic.List<CodeClass> result = new System.Collections.Generic.List<CodeClass>();
FindClasses(GetProject().CodeModel.CodeElements, className, baseClassName, nameSpace, result, false);
return result;
}
private void FindClasses(CodeElements elements, string className, string baseClassName, string searchNamespace, List<CodeClass> result, bool isNamespaceOk)
{
if (elements == null) return;
foreach (CodeElement element in elements)
{
if (element is EnvDTE.CodeNamespace)
{
EnvDTE.CodeNamespace ns = element as EnvDTE.CodeNamespace;
if (ns != null)
{
if (ns.FullName == searchNamespace)
FindClasses(ns.Members, className, baseClassName, searchNamespace, result, true);
else
FindClasses(ns.Members, className, baseClassName, searchNamespace, result, false);
}
}
else if (element is CodeClass && isNamespaceOk)
{
CodeClass c = element as CodeClass;
if (c != null)
{
if (c.FullName.Contains(className) && (baseClassName == null || (HasIt(c.Bases, baseClassName) && c.Name != baseClassName)))
result.Add(c);
FindClasses(c.Members, className, baseClassName, searchNamespace, result, true);
}
}
}
}
private bool HasIt(CodeElements elements, string name)
{
foreach (CodeElement element in elements)
{
CodeClass c = element as CodeClass;
if (c != null && c.Bases != null)
{
if (HasIt(c.Bases, name))
{
return true;
}
}
if (element.Name == name)
return true;
}
return false;
}
private Project GetProject()
{
IServiceProvider serviceProvider = (IServiceProvider)this.Host;
DTE dte = serviceProvider.GetService(typeof(DTE)) as DTE;
// Get DTE
//var dte = (DTE)TransformationContext.Current.GetService(typeof(DTE));
// Get ProjectItem representing the template file
ProjectItem projectItem = dte.Solution.FindProjectItem(this.Host.TemplateFile);
// Get the Project of the template file
Project project = projectItem.ContainingProject;
return project;
}
private string GetDefaultNamespace()
{
IServiceProvider serviceProvider = (IServiceProvider)this.Host;
DTE dte = serviceProvider.GetService(typeof(DTE)) as DTE;
// Get DTE
//var dte = (DTE)TransformationContext.Current.GetService(typeof(DTE));
// Get ProjectItem representing the template file
ProjectItem projectItem = dte.Solution.FindProjectItem(this.Host.TemplateFile);
// Get the Project of the template file
Project project = projectItem.ContainingProject;
var vsSolution = (IVsSolution)serviceProvider.GetService(typeof(SVsSolution));
IVsHierarchy vsHierarchy;
ErrorHandler.ThrowOnFailure(vsSolution.GetProjectOfUniqueName(project.FullName, out vsHierarchy));
uint projectItemId;
ErrorHandler.ThrowOnFailure(vsHierarchy.ParseCanonicalName(projectItem.FileNames[1], out projectItemId));
object defaultNamespace;
ErrorHandler.ThrowOnFailure(vsHierarchy.GetProperty(projectItemId, (int)VsHierarchyPropID.DefaultNamespace, out defaultNamespace));
return ((string)defaultNamespace);
}
#>
为什么不使用TFS构建服务器来自动构建? – Kar
因为整个部署过程涉及多个更复杂的步骤。 – Luis
因为我们没有TFS。因为我想要一个简单,易于配置,灵活的机制,最好基于命令行。所以,TFS构建服务器在这里不是一个选项。 – Luis