Search code examples
c#-4.0asp.net-mvc-5t4

How do I change a T4 Template to add Serializable to generated classes?


As the question says I would like to add [Serializable] to classes generated from a T4 Template .tt file. As far as the information I found gave me, is that I could put using System.Runtime.Serialization; and [Serializable] as plain text in the .tt file as a "Text block". Except it won't generate these in the output files.

<#
    EndNamespace(code);
}

foreach (var complex in typeMapper.GetItemsToGenerate<ComplexType>(itemCollection))
{
    fileManager.StartNewFile(complex.Name + ".cs");
    BeginNamespace(code);
#>
<#=codeStringGenerator.UsingDirectives(inHeader: false, includeCollections: false)#>
using System.Runtime.Serialization;

[Serializable]
<#=Accessibility.ForType(complex)#> partial class <#=code.Escape(complex)#>
{
<#
    var complexProperties = typeMapper.GetComplexProperties(complex);
    var propertiesWithDefaultValues = typeMapper.GetPropertiesWithDefaultValues(complex);

    if (propertiesWithDefaultValues.Any() || complexProperties.Any())

T4 Template code

//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated from a template.
//
//     Manual changes to this file may cause unexpected behavior in your application.
//     Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

namespace Projectnamespace.Models
{
    using System;
    using System.Collections.Generic;
    
    public partial class Customer
    {
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]

Generated code

I would love to know if there is a special syntax for this or something I have to change to get this to work.

I am using Visual Studio 2019, .NET Framework 4.7.2, an MVC 5 project and an .edmx file for the database.


Solution

  • Well.. Eventually I found a way to add "using System.Runtime.Serialization;" and "[Serializable]" in every class by adding some line to the UsingDirectives method in the T4 Template. By changing this:

        public string UsingDirectives(bool inHeader, bool includeCollections = true)
        {
            return inHeader == string.IsNullOrEmpty(_code.VsNamespaceSuggestion())
                ? string.Format(
                    CultureInfo.InvariantCulture,
                    "{0}using System;{1}" +
                    "{2}",
                    inHeader ? Environment.NewLine : "",
                    includeCollections ? (Environment.NewLine + "using System.Collections.Generic;") : "",
                    inHeader ? "" : Environment.NewLine)
                : "";
        }
    

    By editing the last row into this:

        public string UsingDirectives(bool inHeader, bool includeCollections = true)
        {
            return inHeader == string.IsNullOrEmpty(_code.VsNamespaceSuggestion())
                ? string.Format(
                    CultureInfo.InvariantCulture,
                    "{0}using System;{1}" +
                    "{2}",
                    inHeader ? Environment.NewLine : "",
                    includeCollections ? (Environment.NewLine + "using System.Collections.Generic;") : "",
                    inHeader ? "" : Environment.NewLine + "using System.Runtime.Serialization;" + Environment.NewLine + "[Serializable]")
                : "";
        }