Sean Holmesby

.NET and Sitecore Developer

By

Easy Cross-Solution Code Generation with inheritance in TDS Classic 5.7

If you want to use Code Generation across multiple TDS projects, you likely need one project to ‘know’ about another. For instance, you will need TDS.MVC.Master to ‘know’ about TDS.MVC.Base, as TDS.MVC.Master has templates in it, that inherit from templates found in TDS.MVC.Base.

As an example, with the projects and templates:-

TDS.MVC.Base
– templates/Global/PageItem

TDS.MVC.Master
– templates/Features/Custom/SpecialCustomPageItem

You might want the code to look like:-

public partial interface IPageItem    // from the template in TDS.MVC.Base
{
  string Title { get; set; }
  string Description { get; set; }
}
 
public partial class SpecialCustomPageItem : IPageItem
{
  // properties for fields found on the PageItem template (found in TDS.MVC.Base)
  public string Title { get; set; }
  public string Description { get; set; }
 
  // Additional field on SpecialCustomPageItem template
  public string Text { get; set; }
}

To have the code generated above (which is somewhat similar to what we have as an example for the Glass T4 templates here), the inheriting project needs to ‘know’ about the base template fields, and therefore, the base project.

TDS Classic 5.0 (released in April 2014) added a ‘Multi-Project Properties’ tab, where you could tell code gen how to ‘know’ about base projects.
Now your code gen could easily recognize the base templates, and include them in your code generation as interfaces, like in the example above.

Cross-Solution Code Gen With Inheritance

This Works OK in a Single Solution, but what about across separate solutions? The multi-project properties can only see the projects in the current solution.

So imagine now that TDS.MVC.Base exists in a separate solution altogether…. Maybe you have multiple solutions deploying to your environment…. and maybe one of those (the base solution) is shared by other projects…

We still want our SpecialCustomPageItem to ‘know’ that it needs to implement IPageItem….and to implement the properties Title and Description from that base template.

In the past…. you could clone the TDS.MVC.Base project into your solution….possibly creating a TDS NuGet package from the original, and importing it into a Cloned, non-deployable project…. just so you can click that checkbox on the Multi-Project Properties page. However this was a lot of effort (and pretty hacky) just to get your base references…

Now, TDS Classic 5.7 gives you the ability to ‘Export Code Gen Reference File’.

When you perform this on the base project, you get a TDS.MVC.Base.codegen.bin file. This is everything to do with code gen for that project.
Now on the Multi-Project Properties page of the inheriting project (the TDS.MVC.Master project in our example), there’s a new section where you can add ‘Code Gen Reference Files’.

Add the exported codegen.bin file in there, and the code generation will treat it as though it was a base project within the solution. Now the code generation can ‘know’ about the base templates through that exported file.

This means the SpecialCustomPageItem class can continue to inherit from IPageItem, and implement the Title and Description properties as before.

Careful with Namespaces

When doing this, depending on your code gen files, you might see that the namespaces in the projects don’t align.

As we could have it, the default namespaces for the TDS.MVC.Base and the TDS.MVC.Master code gen may be different…. so, using something like the example Glass Mapper T4 templates, the generated code won’t compile due to a mis-matching namespace being created between the two solutions.
The thing is, those T4 template files *are just an example*. You can do whatever you like in them….

You can check what is available to you for code generation using the Doc Item template example.

Looking at this, you can either use item.TargetProjectName (assuming you’re matching the namespace to the project name and nested folders, as in the example here).
Or better yet, you can set a custom ‘Additional Property’ in the base project:-

and use that key in the code gen.

if (item.AdditionalProperties.ContainsKey("BaseProjectNamespace"))
{
    string startingNamespace = item.AdditionalProperties["BaseProjectNamespace"];
    //do something to build full namespace
}

As with the Glass Mapper T4 Template examples, you would locate the GetNamespace method in the Helpers.tt file, and change it to this.

public static string GetNamespace(string defaultNamespace, SitecoreItem item, bool includeGlobal = false)
{
  List<string> namespaceSegments = new List<string>();
  //START Modified section
  if (item.AdditionalProperties.ContainsKey("BaseProjectNamespace"))
  {
    namespaceSegments.Add(item.AdditionalProperties["BaseProjectNamespace"]);
  }
  //END Modified section
  namespaceSegments.Add(defaultNamespace);
  namespaceSegments.Add(item.Namespace);
  string @namespace = AsNamespace(namespaceSegments); // use an extension method in the supporting assembly
 
  return includeGlobal ? string.Concat("global::", @namespace) : @namespace;
}

Links:

Multi-Project Properties: https://www.teamdevelopmentforsitecore.com/Blog/tds-project
Multi-Project Properties Docs: https://www.hhogdev.com/help/tds/propmulti
Namespace Differences across inherited projects: https://stackoverflow.com/questions/31711197/sitecore-tds-multi-project-properties-base-template-reference-not-working-for-me
Code Gen with Inheritance in a Helix Solution: https://sitecore.stackexchange.com/questions/5882/auto-generating-glass-models-in-helix-implementation/7330

Leave a Reply

Your email address will not be published. Required fields are marked *