2010-08-23 4 views
13

Ich habe eine Lösung, die ein paar Projekte enthält. Ich möchte einige T4-Vorlagen in einem meiner Testprojekte erstellen, um Tests basierend auf Code in einem anderen Projekt zu generieren. Das Testprojekt verfügt über eine Projektreferenz für das andere Projekt. Das Problem, das ich habe, ist, dass ich nicht weiß, wie man einen Dateipfad zu der edmx-Datei bekommt, von der ich Code erzeugen muss.Get referenzierten Projektpfad in T4-Vorlage?

Beispiel (so tun, dies ist eine ASCII-basierte Lösung Explorer):

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) 

Wie würde mein GeneratedTests.tt der Lage sein, einen Dateipfad zu bekommen für MyModel.edmx es seinen Projektverweis verwendet?

Antwort

4

Dies funktioniert nicht so. Sie müssen die DLL nach Pfad referenzieren (Sie können das mit Host.ResolvePath herausfinden und das VolatileAssembly-Tag aus der Toolbox verwenden, um es neu kompilieren zu können, ohne VS neu zu starten) und reflection verwenden, um am Model zu arbeiten.

+0

Verweis auf die DLL nach Pfad verursacht das Problem, das ich versuche zu vermeiden. Eine Entwicklungsabteilung kann das Projekt an einem Ort haben, während ein anderer es an einem anderen Ort hat. Wenn ich den Standort annehmen könnte, müsste ich das Template nicht bestimmen lassen - ich könnte es einfach fest codieren oder es mit Build-Skripten injizieren. Die Arbeit am Modell ist kein Problem - mein Skript läuft perfekt, wenn ich den Pfad fest codiere. Ich brauche nur eine Möglichkeit, diesen Pfad dynamisch zu bestimmen. Die Verwendung von Host.Resolve ist in Ordnung, wenn ich den Pfad der Vorlage brauche - ich muss nur den Pfad für die Quelle der MyDAL-Assembly herausfinden. – Jaxidian

+2

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

1

Sie können die Makros für spezielle Verzeichnisse wie $(ProjectDir), $(SolutionDir) aus der Vorlage verwenden und lesen Sie möglicherweise die .sln oder .csproj-Datei, um das Verzeichnis für das andere Projekt zu extrahieren.

+0

Ich hatte gehofft, zu vermeiden, die .sln-Datei zu lesen - ich vermute meistens, weil ich es nicht so gut verstehe und ich bin mir nicht sicher, welche Annahmen ich machen kann, wie zuverlässig der Pfad dort ist. Kannst du mir irgendwelche Links geben, um das besser zu verstehen, vielleicht? – Jaxidian

+0

Eigentlich glaube ich nicht, dass es geeignet ist. Diese Makros scheinen nur in den T4-Direktiven wie '<# @ assembly #>' und '<#@include #>' –

+6

zu funktionieren. Wenn Sie einen Makropfad außerhalb einer T4-Direktive auflösen müssen, verwenden Sie: 'strPath = Host.ResolveAssemblyReference ("$ (ProjectDir)") ', ResolvePath funktioniert nicht mit Makros - eine zukünftige Verbesserung vielleicht? –

15

Diese Antwort funktioniert nur in Visual Studio.

Legen Sie die "hostspezifische" Eigenschaft der T4-Vorlage fest. Dadurch erhalten Sie Zugriff auf die Host-Eigenschaft. Geben Sie cast Host in IServiceProvider ein, um GetService (typeof (DTE)) aufzurufen. Dadurch können Sie den Inhalt der Lösung durchlaufen.

<#@ 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#> 
<# 
} 
#> 

Siehe auch das Beispiel der ITextTemplatingEngineHost interface on MSDN und T4 Architecture by Oleg Synch.

+0

Ich denke, das wird gut für mich funktionieren, wenn es so funktioniert, wie es sich anhört. Können Sie jedoch Ihren Kommentar erläutern, dass dies nur in Visual Studio funktioniert? Wir planen, unsere Vorlagengenerationen zu automatisieren, da wir damit beginnen, sie alle auf unsere Lösung zu übertragen, da es immer schmerzhafter wird, alles manuell zu durchlaufen und zu generieren. Wir wissen nicht genau, wie wir es automatisieren, daher kann uns Ihre Antwort helfen, es zu planen. Nant, PS/MSBuild, was auch immer - uns geht es gut, aber es ist notwendig, es zu tun. – Jaxidian

+0

Wenn Sie hostspecific = "true" festlegen, erhält die Vorlage Zugriff auf den Host-Parameter. Aber der Nachteil ist, dass der T4-Host es bereitstellen muss. In diesem Fall wird angenommen, dass der T4-Host Visual Studio ist, der die DTE-Schnittstelle implementiert. Das Build der Befehlszeile würde null zurückgeben. Wenn Sie diese Methode verwenden möchten, empfehle ich, dass Sie Ihre Vorlagen in Visual Studio, nicht innerhalb des Builds, transformieren. Der automatisierte Build kann den generierten Code verwenden. –

4

Gebrauch diese Linien

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

dann relativen Pfad verwenden, um Ihre edmx Datei zu erhalten z.B. String inputfile = @ ".. \ Modal.edmx";

10

Basiert weg von James Schließen Kommentar konnte ich die folgende Vorlage schreiben für das Debuggen von meiner Dateipfade:

<#@ 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 
    <# 
} 
#> 

Dies wird eine TXT-Datei generieren und werden Sie sehr schnell, ob helfen Debuggen Weg könnte sein oder nicht sein.

Als eine Randnotiz, in denen es einen relativen Verzeichnispfad gab (zB ../App.config), der nicht gefunden werden konnte, half es mir, eine Datei (zB test1.txt) auf jede Verzeichnisebene zu legen aus, dass Host.ResolvePath war nicht in der Lage, mit meinem Setup außerhalb der aktuellen Baugruppe zu sehen. Dieser Vorbehalt kann sehr schnell verwirrend sein, da ../../App.config zu MySolution\App.config aufgelöst werden kann, aber ../../MyDal/README.txt wird nicht aufgelöst (daher wird die Datei nicht gefunden), selbst wenn das der richtige Pfad ist. Der obige Code scheint dieses Problem, soweit ich sehen kann, zu negieren.

Die obige Lösung könnte auch eine Lösung für dieses Problem sein - How to use the poco entity generator

0

Basierend auf der Antwort von Mina und anderen, die ich mit dieser Lösung kam. Es listet das aktuelle Arbeitsverzeichnis, den Lösungspfad auf und verwendet den Trick von Mina, um das aktive Arbeitsverzeichnis zu ändern.

<#@ 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 #> 
Verwandte Themen