Code Generation Framework

The Code Generation Framework is part of the Software Factory runtime and can be used to generate sourcecode within the context of a single ModelElement. Every ModelElement for which sourcecode can be generated should implement the IArtifactLinkContainer interface. When generating code for a ModelElement, this interface is used to obtain a List of ArtifictLinks. Every ModelElement should return an ArtifactLink for each ProjectItem that should be generated, as well as all the ProjectItems it depends on.

The Code Generation Framework will automatically show a “Generate Code”-context menu item for ModelElements that implement this interface and return more than 1 ArtifactLink.If a model element implements the IArtifactLinkContainer interface, but is not fit to generate code off, it can return an empty list of Artifact Links, this will hide the “Generate Code”-context menu item.

 public interface IArtifactLinkContainer
 	ICollection<IArtifactLink> ArtifactLinks { get; }
public interface IArtifactLink
 	//The ProjectGuid this ProjectItem belongs.
 	Guid Container { get; }
 	//The Path of the ProjectItem inside the Project.
 	string ItemPath { get; }

If a Model Element does not derive from IArtifictLinkCotnainer, but from IExtensibleObject the Code Generation Framework wil check wether the ObjectExtender implements IArtifiactLinkContainer instead and it will generate ProjectItems of the ObjectExtender instead.

Determining which Project Item belongs to which Project

In order to have more flexibility on to which projects the generated ProjectItems should be added, a Project Mapping Table exists. The Project Mapping Table is stored in a xml-file called ProjectMapping.xml and contains a mapping from a Project to a Role.

 <?xml version="1.0"?>
 <ProjectMappingInformation xmlns:xsi="" 
  xmlns:xsd="" FileName="ProjectMapping.xml" 
     <ProjectMappingTable Name="WCF">
         <ProjectMapping *ProjectId="c8049784-770e-403b-974b-aaccd77b0d9e" ProjectPath="\">*
             <Role Name="*ServiceContractRole*" />
         <ProjectMapping *ProjectId="abc7d224-770e-403b-974b-aaccd77b0d9e" ProjectPath="\">*
             <Role Name="*FaultContractRole*" />
             <Role Name="*DataContractRole*" />

These roles correspond to attributes used on the Model Elements. when generating code the Project Mapping Table from the model is used to figure out which Artifact Link belongs to which project.

 public partial class Service : DslModeling::ModelElement

The Project Mapping file allows for multiple Project Mapping Tables to coexist, which makes it possible to generate code from the same model to multiple target-projects.

List of Roles by the Services Factory:

DataContractRole Maps target project for Data Contracts
FaultContractRole Maps target project for Fault Contracts
MessageContractRole Maps target project for Message Contracts
ServiceContractRole Maps target project for Service Contracts
ServiceRole Maps target project for Service Implementation
HostRole Maps target project for the Host

Specifying a Code Generation Strategy

When the CodeGeneration Strategy Generates a ProjectItem from an ArtifactLink, this is done by a CodeGenerationStrategy. The CodeGenerationStrategy is a means of generating code.
For example, generating code by transforming a T4 template is done through the TextTemplateCodeGenerationStrategy. Each Link should specify the CodeGeneration Strategy it should be transformed with by means of a CustomAttribute CodeGenerationStrategyAttribute that takes the type of the strategy as an argument. The CodeGenerationStrategy should implement an interface called ICodeGenerationStrategy which contains a method string Generate(IArtifactLink link)that is used to generate the actual content of the ProjectItem. Additionally the CodeGenerationStrategy can specify a list of Projects or Assemblies that should be added to the target project, when the ProjectItem is generated.

 public interface ICodeGenerationStrategy
 	/// <summary>
 	/// Generates code according to the specified link information.
 	/// </summary>
 	/// <param name="link">The link.</param>
 	/// <returns></returns>
 	string Generate(IArtifactLink link);
 	/// <summary>
 	/// Gets the project references.
 	/// </summary>
 	/// <value>The project references.</value>
 	IList<Guid> ProjectReferences { get;}
 	/// <summary>
 	/// Gets the assembly references.
 	/// </summary>
 	/// <value>The project references.</value>
 	IList<string> AssemblyReferences { get;}

Using the TextTemplateCodeGenerationStrategy

The ServiceFactory ships with a TextTemplateCodeGenerationStrategy out of the box. This CodeGenerationStrategy can be used to generate ProjectItems using a TextTemplate. To use the the TextTemplatingStrategy for an Artifact link you should first specify this through CodeGenerationStrategyAttribute and derive from the abstract ArtifactLink class. The ArtifactLink baseclass already implements an interface called ITextTemplateReference as well as the IModelReference. These interfaces are required by the TextTemplatingCodeGenerationStrategy and used to retrieve the template and the ModelElement that should be used for transformation. The ArtifactLink base class also requires the Derived class to specify a TextTemplateAttribute. This TextTemplateAttribute refers to the actual TextTemplate, which can either be a file on disk or a resource in the ArtifiactLinks assembly.

 [TextTemplate (*@"c:\somewhere\Subfolder\")]*
 public class MyArtifactLink : *ArtifactLink*, ...

If the TextTemplating engine needs to import assemblies while executing (because they are referenced from within the templates content) These references should be declared on the ArtifactLink, using the AssemblyReference attribute, passing the AssemblyName as an argument.

The imported assembly should be contained in either the GAC or in VisualStudio’s probing paths in order for resolution to succeed.

 * [AssemblyReference ("AssemblyName, Version=, Culture=neutral, PublicKeyToken=(null)")]*
 [TextTemplate (@"c:\somewhere\Subfolder\")]
 public class MyArtifactLink : ArtifactLink, ...

The ModelInjectorDirectiveProcessor

The CodeGeneration Framework expsoses a DirectiveProcessor called ModelInjectorDirectiveProcessor that can be used inside a TextTemplate, when generating code. The DirectiveProcessor can be included in a template, by adding the following line to the list of directives in a TextTemplate:

 <#@ ModelInjector processor="ModelInjectorDirectiveProcessor" #>

If the TextTemplateCodeGenerationStrategy finds such a directive, it adds contextual information to the Template that can be used when generating code. This contextual information is exposed as properties and methods inside the Template. The list of Properties and Methods available inside the TextTemplate when generating code:

Model {get;} A reference to the model that was used to generate code from.
RootElement {get;} The root-elelemt of the Model that was used to generate code from
CurrentElement {get;} The element that was used to generate code from
CurrentExtender {get;} The ObjectExtender of the element that was used to generate code from. If available
ToCamelCase(string) Creates a camelcased identifier given a string
ResolveModelReference(string) Takes a ModelElementMoniker and returns the referenced ModelElement from a different model.
AddProjectReference(IArtifactLink) Adds a project reference to the project another artifact link is contained in.

Last edited May 12, 2007 at 7:11 AM by donsmith, version 1


No comments yet.