Aracılığıyla paylaş


Metin şablonlarından modellere erişme

Metin şablonlarını kullanarak, etki alanına özgü dil modellerini temel alan rapor dosyaları, kaynak kod dosyaları ve diğer metin dosyaları oluşturabilirsiniz. Metin şablonları hakkında temel bilgiler için bkz . Kod Oluşturma ve T4 Metin Şablonları. DSL'nizde hata ayıklarken metin şablonları deneysel modda çalışır ve DSL'yi dağıttığınız bir bilgisayarda da çalışır.

Not

DSL çözümü oluşturduğunuzda, hata ayıklama projesinde örnek metin şablonu *.tt dosyaları oluşturulur. Etki alanı sınıflarının adlarını değiştirdiğinizde, bu şablonlar artık çalışmaz. Bununla birlikte, bunlar ihtiyacınız olan temel yönergeleri içerir ve DSL'nizle eşleşecek şekilde güncelleştirebileceğiniz örnekler sağlar.

Metin şablonundan modele erişmek için:

  • Şablon yönergesinin inherit özelliğini Microsoft.VisualStudio.TextTemplating.VSHost.ModelingTextTransformation olarak ayarlayın. Bu, Mağaza'ya erişim sağlar.

  • Erişmek istediğiniz DSL için yönerge işlemcilerini belirtin. Bu işlem DSL'nizin derlemelerini yükler; böylece metin şablonunuzun kodunda etki alanı sınıflarını, özelliklerini ve ilişkilerini kullanabilirsiniz. Ayrıca, belirttiğiniz model dosyasını yükler.

    .tt DSL Minimal Dil şablonundan yeni bir Visual Studio çözümü oluşturduğunuzda Hata Ayıklama projesinde aşağıdaki örneğe benzer bir dosya oluşturulur.

<#@ template inherits="Microsoft.VisualStudio.TextTemplating.VSHost.ModelingTextTransformation" #>
<#@ output extension=".txt" #>
<#@ MyLanguage processor="MyLanguageDirectiveProcessor" requires="fileName='Sample.myDsl1'" #>

This text will be output directly.

This is the name of the model: <#= this.ModelRoot.Name #>

Here is a list of elements in the model:
<#
  // When you change the DSL Definition, some of the code below may not work.
  foreach (ExampleElement element in this.ExampleModel.Elements)
  {#>
<#= element.Name #>
<#
  }
#>

Bu şablonla ilgili aşağıdaki noktalara dikkat edin:

  • Şablon, DSL Tanımında tanımladığınız etki alanı sınıflarını, özelliklerini ve ilişkilerini kullanabilir.

  • Şablon, özelliğinde requires belirttiğiniz model dosyasını yükler.

  • içindeki this bir özellik kök öğesini içerir. Buradan kodunuz modelin diğer öğelerine gidebilir. Özelliğin adı genellikle DSL'nizin kök etki alanı sınıfıyla aynıdır. Bu örnekte bu değer this.ExampleModel’dur.

  • Kod parçalarının yazıldığı dil C# olsa da, herhangi bir türde metin oluşturabilirsiniz. Visual Basic'te, özelliğini language="VB" yönergesine template ekleyerek alternatif olarak kodu yazabilirsiniz.

  • Şablonda hata ayıklamak için yönergesine template ekleyindebug="true". Özel durum oluşursa şablon Visual Studio'nun başka bir örneğinde açılır. Kodun belirli bir noktasında hata ayıklayıcıya girmek istiyorsanız deyimini ekleyin System.Diagnostics.Debugger.Break();

    Daha fazla bilgi için bkz . T4 Metin Şablonunda Hata Ayıklama.

DSL yönerge işlemcisi hakkında

Şablon, DSL Tanımınızda tanımladığınız etki alanı sınıflarını kullanabilir. Bu, genellikle şablonun başlangıcına yakın bir noktada görünen bir yönerge tarafından getirilir. Önceki örnekte aşağıdaki gibidir.

<#@ MyLanguage processor="MyLanguageDirectiveProcessor" requires="fileName='Sample.myDsl1'" #>

Yönergesinin adı ( MyLanguagebu örnekte), DSL'nizin adından türetilmiştir. DSL'nizin bir parçası olarak oluşturulan bir yönerge işlemcisi çağırır. Kaynak kodunu Dsl\GeneratedCode\DirectiveProcessor.cs içinde bulabilirsiniz.

DSL yönerge işlemcisi iki asıl görev gerçekleştirir:

  • DSL'nize başvuran şablona derleme ve içeri aktarma yönergelerini etkili bir şekilde ekler. Bu, şablon kodunda etki alanı sınıflarınızı kullanmanıza olanak tanır.

  • parametresinde requires belirttiğiniz dosyayı yükler ve içinde yüklü modelin kök öğesine başvuran bir özellik this ayarlar.

Şablonu çalıştırmadan önce modeli doğrulama

Şablon yürütülmeden önce modelin doğrulanması için neden olabilirsiniz.

<#@ MyLanguage processor="MyLanguageDirectiveProcessor" requires="fileName='Sample.myDsl1';validation='open|load|save|menu'" #>

Şunlara dikkat edin:

  1. filename ve validation parametreleri ";" ile ayrılır ve başka ayırıcılar veya boşluklar olmamalıdır.

  2. Doğrulama kategorilerinin listesi, hangi doğrulama yöntemlerinin yürütüleceğini belirler. Birden çok kategori "|" ile ayrılmalıdır ve başka ayırıcı veya boşluk olmamalıdır.

    Hata bulunursa, hata penceresinde raporlanır ve sonuç dosyası bir hata iletisi içerir.

Metin şablonundan birden çok modele erişme

Not

Bu yöntem, aynı şablondaki birden çok modeli okumanızı sağlar, ancak ModelBus başvurularını desteklemez. ModelBus Başvuruları ile birbirine bağlantısı olan modelleri okumak için bkz . Metin Şablonunda Visual Studio ModelBus kullanma.

Aynı metin şablonundan birden fazla modele erişmek istiyorsanız, oluşturulan yönerge işlemcisini her model için bir kez çağırmanız gerekir. Parametresinde her modelin requires dosya adını belirtmeniz gerekir. parametresinde kök etki alanı sınıfı provides için kullanmak istediğiniz adları belirtmelisiniz. Yönerge çağrılarının her birinde parametreler için provides farklı değerler belirtmelisiniz. Örneğin, Library.xyz, School.xyz ve Work.xyz adlı üç model dosyanız olduğunu varsayalım. Bunlara aynı metin şablonundan erişmek için aşağıdakine benzer üç yönerge çağrısı yazmanız gerekir.

<#@ ExampleModel processor="<YourLanguageName>DirectiveProcessor" requires="fileName='Library.xyz'" provides="ExampleModel=LibraryModel" #>
<#@ ExampleModel processor="<YourLanguageName>DirectiveProcessor" requires="fileName='School.xyz'" provides="ExampleModel=SchoolModel" #>
<#@ ExampleModel processor="<YourLanguageName>DirectiveProcessor" requires="fileName='Work.xyz'" provides="ExampleModel=WorkModel" #>

Not

Bu örnek kod, En Az Dil çözüm şablonunu temel alan bir dile yöneliktir.

Metin şablonunuzdaki modellere erişmek için, aşağıdaki örnekteki koda benzer bir kod yazabilirsiniz.

<#
foreach (ExampleElement element in this.LibraryModel.Elements)
...
foreach (ExampleElement element in this.SchoolModel.Elements)
...
foreach (ExampleElement element in this.WorkModel.Elements)
...
#>

Modelleri dinamik olarak yükleme

Çalışma zamanında hangi modellerin yükleneceğini belirlemek istiyorsanız, DSL'ye özgü yönergesini kullanmak yerine program kodunuzda dinamik olarak bir model dosyası yükleyebilirsiniz.

Ancak, DSL'ye özgü yönergenin işlevlerinden biri DSL ad alanını içeri aktarmaktır, böylece şablon kodu bu DSL'de tanımlanan etki alanı sınıflarını kullanabilir. yönergesini kullanmadığınız için yükleyebileceğiniz tüm modeller için derleme> ve< içeri aktarma> yönergeleri eklemeniz <gerekir. Yükleyebileceğin farklı modellerin tümü aynı DSL'nin örnekleriyse bu kolaydır.

Dosyayı yüklemek için en etkili yöntem Visual Studio ModelBus kullanmaktır. Tipik bir senaryoda, metin şablonunuz ilk modeli normal şekilde yüklemek için DSL'ye özgü bir yönerge kullanır. Bu model, başka bir modele ModelBus Başvuruları içerir. ModelBus kullanarak başvuruda bulunan modeli açabilir ve belirli bir öğeye erişebilirsiniz. Daha fazla bilgi için bkz . Metin Şablonunda Visual Studio ModelBus kullanma.

Daha az olağan bir senaryoda, yalnızca dosya adına sahip olduğunuz ve geçerli Visual Studio projesinde bulunmayan bir model dosyası açmak isteyebilirsiniz. Bu durumda, Nasıl yapılır: Program Kodunda Dosyadan Model Açma başlığı altında açıklanan tekniği kullanarak dosyayı açabilirsiniz.

Şablondan birden çok dosya oluşturma

Örneğin, bir modeldeki her öğe için ayrı bir dosya oluşturmak üzere birkaç dosya oluşturmak istiyorsanız, birkaç olası yaklaşım vardır. Varsayılan olarak, her şablon dosyasından yalnızca bir dosya oluşturulur.

Uzun bir dosyayı bölme

Bu yöntemde, sınırlayıcıyla ayrılmış tek bir dosya oluşturmak için bir şablon kullanırsınız. Ardından dosyayı bölümlerine bölersiniz. Biri tek dosyayı oluşturmak, diğeri de bölmek için olmak üzere iki şablon vardır.

LoopTemplate.t4 uzun tek dosyayı oluşturur. Dosya uzantısının ".t4" olduğuna dikkat edin, çünkü Tüm Şablonları Dönüştür'e tıkladığınızda doğrudan işlenmemelidir. Bu şablon, segmentleri ayıran sınırlayıcı dizesini belirten bir parametre alır:

<#@ template inherits="Microsoft.VisualStudio.TextTemplating.VSHost.ModelingTextTransformation" #>
<#@ parameter name="delimiter" type="System.String" #>
<#@ output extension=".txt" #>
<#@ MyDSL processor="MyDSLDirectiveProcessor" requires="fileName='SampleModel.mydsl1';validation='open|load|save|menu'" #>
<#
  // Create a file segment for each element:
  foreach (ExampleElement element in this.ExampleModel.Elements)
  {
    // First item is the delimiter:
#>
<#= string.Format(delimiter, element.Id) #>

   Element: <#= element.Name #>
<#
   // Here you generate more content derived from the element.
  }
#>

LoopSplitter.ttLoopTemplate.t4öğesini çağırır ve ardından sonuçta elde edilen dosyayı kendi kesimlerine böler. Modeli okumadığı için bu şablonun bir modelleme şablonu olması gerekmediğine dikkat edin.

<#@ template hostspecific="true" language="C#" #>
<#@ output extension=".txt" #>
<#@ import namespace="Microsoft.VisualStudio.TextTemplating" #>
<#@ import namespace="System.Runtime.Remoting.Messaging" #>
<#@ import namespace="System.IO" #>

<#
  // Get the local path:
  string itemTemplatePath = this.Host.ResolvePath("LoopTemplate.t4");
  string dir = Path.GetDirectoryName(itemTemplatePath);

  // Get the template for generating each file:
  string loopTemplate = File.ReadAllText(itemTemplatePath);

  Engine engine = new Engine();

  // Pass parameter to new template:
  string delimiterGuid = Guid.NewGuid().ToString();
  string delimiter = "::::" + delimiterGuid + ":::";
  CallContext.LogicalSetData("delimiter", delimiter + "{0}:::");
  string joinedFiles = engine.ProcessTemplate(loopTemplate, this.Host);

  string [] separateFiles = joinedFiles.Split(new string [] {delimiter}, StringSplitOptions.None);

  foreach (string nameAndFile in separateFiles)
  {
     if (string.IsNullOrWhiteSpace(nameAndFile)) continue;
     string[] parts = nameAndFile.Split(new string[]{":::"}, 2, StringSplitOptions.None);
     if (parts.Length < 2) continue;
#>
 Generate: [<#= dir #>] [<#= parts[0] #>]
<#
     // Generate a file from this item:
     File.WriteAllText(Path.Combine(dir, parts[0] + ".txt"), parts[1]);
  }
#>