Customizing Code Generation

You can edit T4 template files to customize the code generation process. Typical customizations include adding properties, adding documentation comments, and updating a configuration file so that a test project has a localhost discovery URL.

The following code example shows the customized BaseMessageClass.cs.t4 file.


                  <#@ assembly name="System.dll" #>
<#@ template language="C#" #>
<#@ property processor="PropertyProcessor" name="TargetNamespace" #>
<#@ property processor="PropertyProcessor" name="ProjectName" #>
<#@ property processor="PropertyProcessor" name="ClassName" #>
#region References
using System;
using System.ServiceModel;
using System.Xml.Serialization;
using System.Runtime.Serialization;
using Microsoft.ConnectedIndustry.ServiceModel.Common;
#endregion

namespace <#= TargetNamespace #>
{
    [Serializable]
    [DataContract(Namespace = "http://<#= TargetNamespace #>")]
    public class <#= ClassName #> : MessageBase
    {

        #region Private Fields
        #endregion

        #region Public Constructors
        /// <summary>
        /// Returns an instance of the <#= ClassName #> class.
        /// </summary>
        public <#= ClassName #>() : base()
        {
        }
        #endregion

        #region Public Properties
        #endregion

    }
}

                

Typically, a T4 file takes the format of directives, followed by code, statements, and expressions. In text templates, you indicate directives by using <#@ tags, statements by using <# tags, and expressions by using <#= tags.

The file contains processing directives that specify the assembly to be used in the template, the language of the template, and the properties that will contain information that a user enters. A mixture of C# code and expressions follows the directives. The C# code is copied directly to the output file, and the user entered properties are copied in place of the expressions. The following example shows the code generated by the BaseMessageClass.cs.t4 file.


                  #region References
using System;
using System.ServiceModel;
using System.Xml.Serialization;
using System.Runtime.Serialization;
using Microsoft.ConnectedIndustry.ServiceModel.Common;
#endregion

namespace MyMessageNameSpace
{
    [Serializable]
    [DataContract(Namespace = "http://MyMessageNameSpace")]
    public class MyMessageClass : MessageBase
    {

        #region Private Fields
        #endregion

        #region Public Constructors
        /// <summary>
        /// Returns an instance of the MyMessageClass class.
        /// </summary>
        public MyMessageClass() : base()
        {
        }
        #endregion

        #region Public Properties
        #endregion

    }
}

                

Adding Properties

You can easily add properties to a T4 file. For example, if all of your DCS services require a message request based upon a city name, you can modify the BaseMessageClass.cs.t4 file to include this property, as shown in the following example.


                  <#@ assembly name="System.dll" #>
<#@ template language="C#" #>
<#@ property processor="PropertyProcessor" name="TargetNamespace" #>
<#@ property processor="PropertyProcessor" name="ProjectName" #>
<#@ property processor="PropertyProcessor" name="ClassName" #>
#region References
using System;
using System.ServiceModel;
using System.Xml.Serialization;
using System.Runtime.Serialization;
using Microsoft.ConnectedIndustry.ServiceModel.Common;
#endregion

namespace <#= TargetNamespace #>
{
    [Serializable]
    [DataContract(Namespace = "http://<#= TargetNamespace #>")]
    public class <#= ClassName #> : MessageBase
    {

        #region Private Fields

        private string _CityName;

        #endregion

        #region Public Constructors
        /// <summary>
        /// Returns an instance of the <#= ClassName #> class.
        /// </summary>
        public <#= ClassName #>() : base()
        {
        }
        #endregion

        #region Public Properties

        [DataMember]
        public string CityName
        {
               get { return _CityName; }
               set { _CityName = value; }
        }

        #endregion

    }
}

                

The following example shows the C# code generated by using this file.


                  #region References
using System;
using System.ServiceModel;
using System.Xml.Serialization;
using System.Runtime.Serialization;
using Microsoft.ConnectedIndustry.ServiceModel.Common;
#endregion

namespace MyMessageNameSpace
{
    [Serializable]
    [DataContract(Namespace = "http://MyMessageNameSpace")]
    public class MyMessageClass : MessageBase
    {

        #region Private Fields

        private string _CityName;

        #endregion

        #region Public Constructors
        /// <summary>
        /// Returns an instance of the MyMessageClass class.
        /// </summary>
        public MyMessageClass() : base()
        {
        }
        #endregion

        #region Public Properties

        [DataMember]
        public string CityName
        {
               get { return _CityName; }
               set { _CityName = value; }
        }

        #endregion

    }
}

                

Adding Documentation Comments

You can add documentation comments to a T4 file. For example, if your organization has a requirement that all classes must have a documentation comment in a specific format, you can automate this process by modifying the appropriate T4 file. You can edit the BaseMessageClass.cs.t4 file to include a class-level documentation comment by adding <summary> tags and using an expression to substitute the class name in the <summary> tag, as shown in the following example.


                  <#@ assembly name="System.dll" #>
<#@ template language="C#" #>
<#@ property processor="PropertyProcessor" name="TargetNamespace" #>
<#@ property processor="PropertyProcessor" name="ProjectName" #>
<#@ property processor="PropertyProcessor" name="ClassName" #>
#region References
using System;
using System.ServiceModel;
using System.Xml.Serialization;
using System.Runtime.Serialization;
using Microsoft.ConnectedIndustry.ServiceModel.Common;
#endregion

namespace <#= TargetNamespace #>
{
    /// <summary>
    /// <#= ClassName #>
    /// </summary>
    [Serializable]
    [DataContract(Namespace = "http://<#= TargetNamespace #>")]
    public class <#= ClassName #> : MessageBase
    {

        #region Private Fields

        private string _CityName;

        #endregion

        #region Public Constructors
        /// <summary>
        /// Returns an instance of the <#= ClassName #> class.
        /// </summary>
        public <#= ClassName #>() : base()
        {
        }
        #endregion

        #region Public Properties

        [DataMember]
        public string CityName
        {
               get { return _CityName; }
               set { _CityName = value; }
        }

        #endregion

    }
}

                

The following example shows the code generated by this using this file.


                  #region References
using System;
using System.ServiceModel;
using System.Xml.Serialization;
using System.Runtime.Serialization;
using Microsoft.ConnectedIndustry.ServiceModel.Common;
#endregion

namespace MyMessageNameSpace
{
    /// <summary>
    /// MyMessageClass
    /// </summary>
    [Serializable]
    [DataContract(Namespace = "http://MyMessageNameSpace")]
    public class MyMessageClass : MessageBase
    {

        #region Private Fields

        private string _CityName;

        #endregion

        #region Public Constructors
        /// <summary>
        /// Returns an instance of the MyMessageClass class.
        /// </summary>
        public MyMessageClass() : base()
        {
        }
        #endregion

        #region Public Properties

        [DataMember]
        public string CityName
        {
               get { return _CityName; }
               set { _CityName = value; }
        }

        #endregion

    }
}

                

Updating an App.config File

To update an App.config file in a Test project to include a localhost discovery URL, edit App.config.t4 and insert the localhost discovery URL in the address attribute of the <mexDiscoveryEndpoint> node, as shown in the following example.


                  <?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <configSections>
        <sectionGroup name="cis.serviceModel"
                 type="Microsoft.ConnectedIndustry.ServiceModel.Application.Configuration.ServiceModelSectionGroup,
                 Microsoft.ConnectedIndustry.ServiceModel.Application,Version=1.0.0.0,Culture=neutral,PublicKeyToken=31bf3856ad364e35">
            <section name="channelFactory"
               type="Microsoft.ConnectedIndustry.ServiceModel.Configuration.ChannelFactorySection,Microsoft.ConnectedIndustry.ServiceModel,Version=1.0.0.0,Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
        </sectionGroup >
    </configSections>
    <cis.serviceModel>
        <channelFactory>
            <mexDiscoveryEndpoint address="http://localhost/myservice/service.asmx" binding="basicHttpBinding" bindingConfiguration="discovery"/>
            <!-- TO DO uncomment the section below to leverage the added support for multiple discovery endpoints-->
            <!--<alternateDiscoveryEndpoints>-->
            <!-- TO DO uncomment section below and add one copy of it for each additional discovery endpoint with priority to define the precedence order for trying it-->
            <!--  <mexDiscoveryEndpoint address="[Add here additional discovery service URL]" binding="basicHttpBinding" bindingConfiguration="[Add here binding Configuration for additional discovery service URL]"
         priority="[Add here priority of current discovery service URL]"/>-->
            <!--</alternateDiscoveryEndpoints>-->
            <scopeRanking type="Microsoft.ConnectedIndustry.ServiceModel.Application.ScopeRanking,Microsoft.ConnectedIndustry.ServiceModel.Application,Version=1.0.0.0,Culture=neutral, PublicKeyToken=31bf3856ad364e35">
            </scopeRanking>
            <scopeProvider type="Microsoft.ConnectedIndustry.ServiceModel.Application.ScopeProvider,Microsoft.ConnectedIndustry.ServiceModel.Application,Version=1.0.0.0,Culture=neutral, PublicKeyToken=31bf3856ad364e35">
            </scopeProvider>
        </channelFactory>
    </cis.serviceModel>
    <system.serviceModel>
        <bindings>
            <basicHttpBinding>
                <binding name="discovery">
                </binding>
            </basicHttpBinding>
        </bindings>
    </system.serviceModel>
    <system.diagnostics>
        <sources>
            <source name="CIS" switchValue="Verbose, Information, ActivityTracing, Critical">
                <listeners>
                    <add name="FileListener"/>
                </listeners>
            </source>
            <source name="Microsoft.ConnectedIndustry.ServiceModel" switchValue="Information, Verbose, Warning, ActivityTracing">
                <listeners>
                    <add name="Debug"/>
                    <add name="FileListener"/>
                </listeners>
            </source>
        </sources>
        <sharedListeners>
            <add logDirectory="C:\Logs" baseFileName="Test_ReqResp" maxFileNumber="5" maxFileSize="100000" textFormatter="{SOURCE} - {MESSAGE}{BR}" type="Microsoft.ConnectedIndustry.ServiceModel.Common.RollFileListener,  Microsoft.ConnectedIndustry.ServiceModel.Common, version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" name="FileListener">
                <filter type=""/>
            </add>
            <add name="Debug" type="System.Diagnostics.DefaultTraceListener" />
        </sharedListeners>
    </system.diagnostics>
</configuration>

                
Show: