TTのCSファイルで独自のクラス定義を使用したいと思います。
例:
public class ClassDefinition
{
public string NameSpace { get; set; }
public string Name { get; set; }
public string Protection { get; set; }
List<ClassProperty> Properties { get; set; }
}
私のTTは次のようになります:
<#@ template debug="true" hostspecific="true" language="C#" #>
<#@ output extension=".cs" #>
<#@ Assembly name="System" #>
<#@ Assembly name="System.Core" #>
<#@ Assembly name="System.Xml"#>
<#@ import namespace="System.Xml" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.IO" #>
<#@ include file="$(ProjectDir)ClassDefinition.cs" #>
<#
// Read the model file
XmlDocument doc = new System.Xml.XmlDocument();
doc.Load(this.Host.ResolvePath("GeneratedXmlFile.xml"));
IList<XmlNode> nodeList = new List<XmlNode>();
foreach (XmlNode node in doc.DocumentElement)
{
switch(node.Name)
{
case "Model":
{
ClassDefinition classDefinition = new ClassDefinition();
しかし、私はこのエラーメッセージを持っています:
変換のコンパイル:タイプまたは名前空間名 'ClassDefinition'が見つかりませんでした(usingディレクティブまたはアセンブリ参照がありませんか?)
私はインターネットをチェックして、次のことを試みました。-インクルードを使用-アセンブリを使用-USINGを使用しかし、何も機能しません。
何か案は ?
完全なソリューションは次のとおりです。
1)クラスを別のプロジェクトに分割します2)TT viaを介してこれらのクラスへの参照を含めます
<#@ Assembly name="$(TargetDir)MyOwnLibraryProject.dll" #>
<#@ import namespace="MyOwnNamespace" #>
3)このライブラリの参照をTTプロジェクトに含めることを忘れないでください
4)MyOwnLibraryProject.dllをTTソリューションのBIN\DEBUGフォルダーにコピーする必要があります
5)魔法が現れる!!!
DLL新しいバージョンをフォルダに入れることを忘れないでください:)または、ライブラリプロジェクトの出力をTT = 1。ガイドラインやアイデアを提供してくれた皆さんに感謝します。
私があなたを正しく理解しているなら、あなたはテンプレート生成の一部としてクラスを再利用しようとしています。
そのクラスはttファイル自体に含まれている必要があり、ビルドアクションはnone、カスタムツール-noneに設定されています。私が持っているのは、上部に次のようなテンプレートマネージャークラスです。
<#@ template language="C#" #>
<#@ Assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.Diagnostics" #>
<#+
public class TemplateManager
{
次に、私が使用する他のt4テンプレートで:
<#@ include file="TemplateManager.tt"#>
その後
List<Values> values = TemplateManager.PrepareVariables(code, container, itemCollection.OfType<EntityType>())
あなたの場合、ClassDefinition.ttファイルには以下が含まれます。
<#@ template language="C#" #>
<#@ Assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.Diagnostics" #>
<#+
public class ClassDefinition
{
public string NameSpace { get; set; }
public string Name { get; set; }
public string Protection { get; set; }
List<ClassProperty> Properties { get; set; }
}
#>
次に、含めることができます
<#@ include file="ClassDefinition.tt"#>
以下を使用して、C#ファイルをT4テンプレートに含めます。
<#@ include file="$(ProjectDir)ClassDefinition.cs" #>
T4テンプレートの出力にテキストを追加します。クラスはコンパイルされません。
T4テンプレートにdebug = trueが設定されているので、%TEMP%ディレクトリを見るとT4が何を生成しているかを確認できます。 T4テンプレートを実行すると、TEMPディレクトリに生成された.csファイルが表示されます。このファイルには、次のようなものがあります。
this.Write("public class ClassDefinition\r\n{\r\n public string NameSpace { get; set; }\r\n p" +
"ublic string Name { get; set; }\r\n public string Protection { get; set; }\r\n\r\n " +
" List<ClassProperty> Properties { get; set; }\r\n}");
したがって、C#クラスで発生しているのは、生成されたT4出力に書き出されることだけです。
おそらくやりたいことは、ClassDefinition.csファイルをプロジェクトに含めて、プロジェクトの一部としてコンパイルすることです。次に、ClassDefinitionクラスを含むアセンブリを参照できます。したがって、プロジェクトの出力がMyLibrary.dllであり、コンパイルされたClassDefinition.csが含まれている場合は、次を使用できるはずです。
<#@ Assembly name="$(SolutionDir)$(OutDir)MyLibrary.dll" #>
ClassDefinition.csファイルを含む行を削除する必要があります。
私自身も同じ問題を抱えていました-私の解決策は@Tehseenのようなものでしたが、実際の解決策を説明とともに提供します:)
任意のC#をT4ファイル(インポートされたC#を単に生のテキストとして含めるのではなくT4で使用する)に含めるコツは、T4がチョークする* .csファイルの部分を非表示にすることです-using
などディレクティブ、およびタイプが<#+
(<#
ではなく)ブロック内で宣言されていることを確認します。
これが私の解決策です:
私の「エントリポイント」MyScript.tt
T4スクリプトは次のようになります。
<#@ template debug="true" hostspecific="false" language="C#" #>
<#@ Assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Text.RegularExpressions" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ include file="IncludedCSFile.cs" #>
<#@ output extension=".cs" #>
<#
MyClass foo = new MyClass(); // This is using a type from `IncludedCSFile.cs` in the T4 script.
#>
Hello, <#= foo.Name #>
私のIncludedCSFile.cs
は次のようになります:
// <#+ /*
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
namespace MyNamespace
{
// */
public class MyClass
{
// etc...
}
}
// #>
// <#+ /*
//
は、(プロジェクトからの)メインC#パーサーがT4 <#+
区切り文字を認識しないようにします。これにより、プロジェクトの構文エラーが発生します。<#+
is T4パーサーによって解析され、ファイル内のC#がT4スクリプトで使用できるコードとして解釈されます。/*
は、T4のC#パーサーがusing...
ステートメントを無視し、namespace MyNamespace
行を開く新しいコメントを開始します。そうしないとT4構文エラーが発生します。using
ステートメントを<#@ import namespace="" #>
ディレクティブとして表現する必要があるためです。// */
<#+
の後ろにある開始ブロックコメントの終了区切り文字です。//
はプロジェクトC#コンパイラ(*/
を認識しません)から/*
を非表示にしますが、T4のC#コンパイラは//
がオーバーライドされるため、それを認識します。前の/*
。// #>
//
トリックを使用して、T4がまだ認識している間にC#から非表示にします。このアプローチにはいくつかの欠点があります。
//
が最終出力ファイルにレンダリングされます。*.ttinclude
ディレクティブのみを含み、<#@ import namespace="" #>
ファイルを含む実際の*.cs
ファイルを作成することです。<#@ template #>
および<#@ output #>
ディレクティブがないため、独自のT4ファイルとして実行できません。ファイルの先頭に配置する必要があることを理解しています。*.ttinclude
ファイルは、とにかく単独で実行することはできません。