How can I use Unicorn to generate Glass Mapper models for my Sitecore items?
2 Answers
The Sitecore.CodeGenerator project can convert serialized Sitecore items into GlassMapper classes, and it contains support for the Rainbow serialization format (used by Unicorn 3).
The project page has step-by-step instructions on how to install and configure it.
-
Is it working with Unicorn 4? I followed GitHub readme instruction, but step 5 doesn't seem to be working In GlassGenerator.tt, change the following code so the path references your serialized data:Context.Host.ResolvePath(@"..\Data\serialization\"). The path is relative to the location of the .tt files.– VincentCommented May 15, 2017 at 7:57
You will have to use Rainbow
(the serialization part of Unicorn) to read the YAML files and the process those with a T4 template.
I have a tool that will do the reading for you and make the objects available in a T4 template. You can use this code for that: https://github.com/Fortis-Collection/fortis.codegen.transitus.rainbow. It is also available as a NuGet package that you can install in your project. Use:
Install-Package Transitus.Rainbow
Once you have this in your project you need to parse the .yml
files.
Example code:
var items = Transitus.Rainbow.TransitusProvider.FolderDeserializer.Deserialize(@"C:\Projects\transitus.rainbow\Files");
var templates = Transitus.Rainbow.TransitusProvider.TemplateFactory.Create(items);
Here is an example T4 template that uses that:
<#@ template debug="true" hostSpecific="true" #>
<#@ output extension=".cs" #>
<#@ assembly Name="System.Core" #>
<#@ assembly Name="System.Windows.Forms" #>
// TODO: Set the paths for the assembly bindings based on the version you have installed
<#@ assembly name="$(SolutionDir)\packages\Rainbow.Core.1.1.0\lib\net45\Rainbow.dll" #>
<#@ assembly name="$(SolutionDir)\packages\Rainbow.Storage.Yaml.1.1.0\lib\net45\Rainbow.Storage.Yaml.dll" #>
<#@ assembly name="$(SolutionDir)\packages\Transitus.Rainbow.1.0.4.0\lib\net45\Transitus.Rainbow.dll" #>
// TODO: make sure the namespace imports include everything you need in your templates
<#@ import namespace="System" #>
<#@ import namespace="System.IO" #>
<#@ import namespace="System.Diagnostics" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.Text.RegularExpressions" #>
<#@ import namespace="System.Globalization" #>
<#@ assembly name="EnvDTE" #>
<#@ import namespace="EnvDTE" #>
<#@ import namespace="Transitus.Rainbow" #>
/*
* Generated Model Templates
*
* Generated at <#= DateTime.Now #>
*/
<#
var stopwatch = Stopwatch.StartNew();
// get the project solution path, we can use this to find the unicorn files
string solutionsPath = this.Host.ResolveAssemblyReference("$(SolutionDir)");
// Set a base path for all unicorn configurations that we want to use
var myFolder = solutionsPath + @"..\Unicorn";
// Add each configuration we want to create models for into a list
var folders = new List<string>
{
myFolder + @"..\Default Configuration\User Defined"
};
#>
<#
var items = new List<IItem>();
foreach (var folder in folders)
{
var deserializedItems = Transitus.Rainbow.TransitusProvider.FolderDeserializer.Deserialize(folder);
items.AddRange(deserializedItems);
}
var templates = Transitus.Rainbow.TransitusProvider.TemplateFactory.Create(items);
#>
using System;
using System.Collections.Generic;
using Sitecore.Data.Items;
using Sitecore.ContentSearch;
using Sitecore.ContentSearch.Linq.Common;
// TODO: Add glass mapper using statements that you need here
<#
foreach (var template in templates)
{
var isRenderingParametersTemplate = HasRenderingOptionsBase(template.BaseTemplateIds, template.Id);
#>
#region <#= template.Name #>
namespace MyProject.Models
{
public partial interface I<#= template.Name #>
{
<#+
foreach(var field in template.LocalFields)
{
#>
/// <summary><para>Template: <#= template.Name #></para><para>Field: <#= field.Name #></para><para>Data type: <#= field.TypeName #></para></summary>
WORKOUTRETURNTYPE <#= field.Name #> { get; }
<#+
}
#>
}
#>
}
#endregion
<#
}
stopwatch.Stop();
#>
// Generated in <#= stopwatch.ElapsedMilliseconds #>ms
// Found <#= templates.Count() #> templates in <#= folders.Count() #> folders [<#= myFolder #>]
There is still a lot to do in that example - but it should give you a start.