2010-08-23 21 views
13

Tengo una solución que tiene algunos proyectos en ella. Me gustaría crear algunas plantillas T4 en uno de mis proyectos de prueba para generar pruebas basadas en el código de otro proyecto. El proyecto de prueba tiene una referencia de proyecto para el otro proyecto. El problema que tengo es que no sé cómo obtener una ruta de archivo al archivo edmx del que necesito generar código.¿Se hace referencia a la ruta del proyecto en la plantilla T4?

Ejemplo (fingir que esto es un Explorador de soluciones basadas en ASCII):

MySolution.sln 
-> MyTests.csproj (C:\a\b\c\) 
----> GeneratedTests.tt (C:\a\b\c\GeneratedTests.tt) 
-> MyDAL.csproj (C:\x\y\z\) 
----> MyModel.edmx (C:\x\y\z\MyModel.edmx) 

¿Cómo sería mi GeneratedTests.tt ser capaz de obtener una ruta de archivo para MyModel.edmx utilizando su referencia de proyecto a la misma?

Respuesta

4

Esto no funciona de esa manera. Tendrá que hacer referencia al dll por ruta (puede encontrarlo con Host.ResolvePath y usar la etiqueta VolatileAssembly desde la caja de herramientas para poder recompilarlo sin reiniciar VS) y usar la reflexión para trabajar en el Modelo.

+0

Al hacer referencia a la DLL por la ruta, se produce el problema que intento evitar. Una caja de desarrollo puede tener el proyecto en un lugar mientras que otro lo tiene en otro lugar. Si pudiera asumir la ubicación, entonces no tendría que tener la plantilla para determinarlo, podría codificarlo o inyectarlo con scripts de compilación. Trabajar en el modelo no es problema: mi script funciona perfectamente si codigo el camino. Solo necesito una forma de determinar dinámicamente ese camino. Usar Host.Resolve está bien si necesito la ruta de acceso de la plantilla, solo necesito encontrar la ruta para el origen del ensamblaje MyDAL. – Jaxidian

+2

Host.ResolvePath (".") Funciona. :) – Jaxidian

1

Puede usar las macros para directorios especiales como $(ProjectDir), $(SolutionDir) de la plantilla, y quizás leer el archivo .sln o .csproj para extraer el directorio del otro proyecto.

+0

Tenía la esperanza de evitar leer el archivo .sln, supongo que principalmente porque no lo entiendo muy bien y no estoy seguro de qué suposiciones puedo hacer acerca de qué tan confiable es el camino allí. ¿Me puede dar algún enlace para entender esto mejor, tal vez? – Jaxidian

+0

En realidad, no creo que sea adecuado. Esas macros solo parecen funcionar en las directivas T4 como '<# @ assembly #>' y '<#@include #>' –

+6

Si necesita resolver una ruta de macro fuera de una directiva T4, puede hacerlo usando: 'strPath = Host.ResolveAssemblyReference ("$ (ProjectDir)") ', ResolvePath no funciona con macros, ¿quizás una mejora futura? –

15

Esta respuesta solo funciona desde Visual Studio.

Establezca la propiedad "hostspecific" de la plantilla T4. Esto le da acceso a la propiedad de Host. Escriba host para IServiceProvider para llamar a GetService (typeof (DTE)). Esto le permite recorrer el contenido de la solución.

<#@ template language="c#" hostspecific="true" #> 
<#@ assembly name="EnvDTE" #> 
<#@ import namespace="EnvDTE" #> 
These are the projects in this solution: 
<# 
var serviceProvider = this.Host as IServiceProvider; 
var dte = serviceProvider.GetService(typeof(DTE)) as DTE; 
foreach (Project p in dte.Solution.Projects) 
{ 
#> 
    <#=p.Name#> at <#=p.FullName#> 
<# 
} 
#> 

Véase también el ejemplo de la ITextTemplatingEngineHost interface on MSDN y T4 Architecture by Oleg Synch.

+0

Creo que esto funcionará bien para mí si funciona como parece. ¿Podrías, sin embargo, explicar tu comentario de que esto solo funciona en Visual Studio? Tenemos planes para automatizar nuestras generaciones de plantillas, ya que estamos empezando a ponerlas sobre nuestra solución, ya que comienza a ser doloroso pasar y generar todo manualmente. No sabemos exactamente cómo lo automatizaremos, por lo que su respuesta puede ayudarnos a planificarlo. Nant, PS/MSBuild, lo que sea, estamos bien haciéndolo, pero es necesario hacerlo. – Jaxidian

+0

Cuando establece hostspecific = "true", la plantilla obtiene acceso al parámetro Host. Pero el inconveniente es que el host T4 debe proporcionarlo. En este caso, se supone que el host T4 es Visual Studio, que implementa la interfaz DTE. La construcción de la línea de comando devolvería nulo. Si desea utilizar este método, le sugiero que modifique sus plantillas dentro de Visual Studio, no dentro de la compilación. La construcción automatizada puede usar el código generado. –

4

uso de estas líneas

string path = this.Host.ResolvePath(""); 
Directory.SetCurrentDirectory(path); 

a continuación, utilizar la ruta relativa para obtener su archivo edmx por ejemplo, cadena ArchivoDeEntrada = @ ".. \ Modal.edmx";

10

Basa en el comentario de James Close, yo era capaz de escribir la siguiente plantilla para la depuración de mis rutas de archivos:

<#@ template language="C#" debug="true" hostspecific="true"#> 
<#@ include file="EF.Utility.CS.ttinclude"#><#@ 
output extension=".txt"#><# 

/////////Some standard-ish settings, continue reading on 
CodeGenerationTools code = new CodeGenerationTools(this); 
MetadataLoader loader = new MetadataLoader(this); 
CodeRegion region = new CodeRegion(this, 1); 
MetadataTools ef = new MetadataTools(this); 

/////////Below are the relevant sections I used for debugging 

    string solutionsPath = Host.ResolveAssemblyReference("$(SolutionDir)");//Gives you the location of MySolution.sln 
    string edmxFile = solutionsPath + "MyDAL/MyDAL/MyModel.edmx"; //Note - VS projects usually have a subdir with the same name as the sln, hence the repetition for MyDAL 
#> 
Does this file exist? 

<# 
// 
if (File.Exists(edmxFile)) 
{ 
    //Continue. 
    #> 
    Yes 
    <# 
} 
else 
{ 
    #> 
    No 
    <# 
} 
#> 

Esto generará un archivo .txt y ayudará muy rápidamente a depurar si su ruta podría estar ubicado o no.

Como nota al margen, en los casos en que existía una ruta de directorios relativa (p.ej. ../App.config) que no se podía ubicar, encontré que ayudó a poner un archivo (por ejemplo, test1.txt) en cada nivel de directorio, como creí que Host.ResolvePath no pudo ver fuera del ensamblaje actual con mi configuración. Esta advertencia puede ser confusa muy rápidamente ya que ../../App.config podría resolverse a MySolution\App.config, pero ../../MyDal/README.txt no se resolverá (por lo tanto, el archivo no se encontrará), incluso si esa es la ruta correcta. El código anterior parece negar este problema por lo que puedo ver.

La solución anterior también podría ser una solución a este problema - How to use the poco entity generator

0

Sobre la base de la respuesta de Mina y otros me ocurrió con esta solución. Enumera el directorio de trabajo actual, la ruta de solución y utiliza el truco de Mina para cambiar el directorio de trabajo activo.

<#@ template debug="true" hostspecific="true" language="C#" #> 
<#@ output extension=".cs" #> 
<#@ import namespace="System.IO" #> 
<#@ assembly name="EnvDTE" #> 
<#@ import namespace="EnvDTE" #> 
<# 
string cwd1 = System.IO.Directory.GetCurrentDirectory(); 
string solutionPath = Host.ResolveAssemblyReference("$(SolutionDir)"); 
Directory.SetCurrentDirectory(solutionPath); 
string cwd2 = System.IO.Directory.GetCurrentDirectory(); 
#> 
// Solutionpath is:<#= solutionPath #>, old cwd: <#= cwd1 #>, new cwd: <#= cwd2 #> 
Cuestiones relacionadas